实现线程
从Java官方文档中可以查看到,无论是JDK8还是JDK11中对线程的实现方式只有两种,一种是继承Thread
类重写run()
方法,一种是实现Runnable
接口实现run()
方法并传递给Thread
类实例
从Thread
源码中也可以看出,无论是哪种方式,最终还是调用Thread
的run()
方法,所以准确的说,创建线程只有一种方式,就是构造Thread
类,而实现线程的执行单元有两种方式
继承Thread类方式
public class MyThread extends Thread{
@Override
public void run() {
System.out.println("继承Thread,复写run()方法");
}
public static void main(String[] args) {
new MyThread().start();
}
}
实现Runnable接口方式
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("实现Runnable,实现run()方法");
}
public static void main(String[] args) {
new Thread(new MyRunnable()).start();
}
}
两种方式对比
通常情况下会优先选择实现Runnable接口方式
-
避免由单继承局限带来的影响
-
从代码架构考虑线程所执行的任务应该与线程创建动作应该是解耦的
-
线程创建的操作对于CPU消耗是比较大的,继承Thread类实现的线程,每次只能新建的独立的线程,而实现Runable接口实现线程,可通过线程池之类的工具来降低创建线程的性能损耗(线程池只能放入Runable或Callable接口实现类,不能直接放入继承Thread的类)
两种方式的本质区别,从Thread
的源码中可以看出,若使用实现Runnable
接口方式,其实是直接执行了run()
方法;若使用继承Thread
类方式其实是将run()
方法进行重写
class Thread implements Runnable {
//省略...
private Runnable target; //用于构造函数接收Runnable接口实例
//省略...
@Override
public void run() {
if (target != null) { //判断该线程中是否接收过Runnable接口实例
target.run();
}
}
//省略...
}
从源码中可以看出,同时使用两种方式实现线程时,实现Runnable
接口方式将失效
public static void main(String[] args) {
new Thread(() -> System.out.println("Runnable中的run()方法")) {
@Override
public void run() {
System.out.println("Thread中的run()方法");
}
}.start();
}
其他封装层面的创建线程方式
虽然多线程的实现方式在代码层面的写法有很多,但是本质上都是对实现Runnable
接口方式,继承Thread
类方式的封装
实现Callable接口方式
public class MyCallable implements Callable<String> {
@Override
public String call() {
System.out.println("当前线程正在执行:" + Thread.currentThread().getName());
return "Callable中的call()方法的返回值";
}
public static void main(String[] args) {
FutureTask<String> futureTask = new FutureTask<>(new MyCallable()); //使用FutureTask类对Callable实现类进行包装
new Thread(futureTask).start(); //使用Thread来启动线程
try {
String result = futureTask.get(); //使用FutureTask的get()方法来线程获取返回值
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
线程池方式
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool(); //创建线程池
for (int i = 0; i < 1000; i++) {
//向线程池中提交1000个任务
executorService.submit(() -> System.out.println("当前线程正在执行:" + Thread.currentThread().getName()));
}
}
定时器方式
public static void main(String[] args) {
Timer timer = new Timer(); //创建定时器
timer.scheduleAtFixedRate(new TimerTask() { //传递定时任务对象
@Override
public void run() {
System.out.println("当前线程正在执行:" + Thread.currentThread().getName());
}
}, 0, 1000); //延时0秒,间隔1秒
}
Comments NOTHING