继承Thread类
通过继承Thread类,并重写它的run方法,我们就可以创建一个线程,然后通过start方法开启线程(开启线程前的代码会先执行完)。不要使用run方法,因为使用run方法会把线程当作普通方法使用,就不是多线程运行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
public class MyThread extends Thread{
@Override public void run() { System.out.println("线程运行"); }
public static void main(String[] args) { Thread thread = new MyThread(); thread.start(); } }
|
实现 Runnable接口
通过实现Runnable,并实现run方法,也可以创建一个线程,这种方法比继承Thread类好
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
public class MyThread implements Runnable{
@Override public void run() { System.out.println("运行线程"); }
public static void main(String[] args) { Thread thread = new Thread(new MyThread()); thread.start(); } }
|
实现 Callable 接口
实现Callable接口,并结合Future实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask;
public class MyThread implements Callable {
@Override public String call() { return "1"; }
public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask task = new FutureTask(new MyThread()); new Thread(task).start(); String result = (String) task.get(); System.out.println(result); } }
|
通过线程池创建线程
用JDK自带的Executors来创建线程池对象(推荐使用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| package thread;
import cn.hutool.core.thread.ThreadFactoryBuilder;
import java.util.concurrent.*;
public class ThreadTest3 implements Runnable {
@Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("玩游戏---" + i); } }
public static void main(String[] args) { int nThreads = Runtime.getRuntime().availableProcessors(); System.out.println(nThreads); ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() .setNamePrefix("demo-pool-%d").build(); ExecutorService executorService = new ThreadPoolExecutor(nThreads, 200, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); executorService.execute(new ThreadTest3()); for (int i = 0; i < 1000; i++) { System.out.println("学习---" + i); } executorService.shutdown(); } }
|
上面代码的ThreadPoolExecutor构造方法的一些参数说明如下(按顺序):
corePoolSize
- 即使空闲时仍保留在池中的线程数,除非设置 allowCoreThreadTimeOut
maximumPoolSize
- 池中允许的最大线程数
keepAliveTime
- 当线程数大于内核时,这是多余的空闲线程在终止前等待新任务的最大时间
unit
- keepAliveTime参数的时间单位
workQueue
- 用于在执行任务之前使用的队列。 这个队列将仅保存execute方法提交的Runnable任务
threadFactory
- 执行程序创建新线程时使用的工厂
handler
- 执行被阻止时使用的处理程序,因为达到线程限制和队列容量
PS.
来源:面试官问我:创建线程有几种方式?我笑了 - SegmentFault 思否
更多线程池的使用查看:线程池的7种创建方式,强烈推荐你用它… - Java中文社群 - 博客园 (cnblogs.com)