如何创建线程?
-
继承
Thread类public class MyThread extends Thread { public void run() { // 线程执行的任务 } }创建线程并启动:
MyThread myThread = new MyThread(); myThread.start(); -
实现
Runnable接口public class MyRunnable implements Runnable { public void run() { // 线程执行的任务 } }创建线程并启动:
Thread thread = new Thread(new MyRunnable()); thread.start();以上代码也可以简化,直接使用匿名内部类或表达式:
// 匿名内部类 Thread thread1 = new Thread(new Runnable() { @Override public void run() { // 线程执行的任务 } }); thread1.start(); // 表达式 Thread thread2 = new Thread(() ->{ // 线程执行的任务 }); thread2.start(); -
实现
Callable接口public class MyCallable implements Callable<Integer> { public Integer call() { // 线程执行的任务,并返回一个结果 } }创建线程对象并启动:
FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable()); Thread thread = new Thread(futureTask); thread.start(); -
使用线程池
ExecutorService executorService = Executors.newFixedThreadPool(1); executorService.execute(new MyRunnable()); executorService.shutdown();
扩展
通过代码可以发现,方法1-3虽然有所不同,但最终都需要通过创建Thread类,并调用start()方法来启动线程,它们有什么关系呢?
Thread类的构造函数
代码中用到的就是Thread()和Thread(Runnable)两个构造方法。
但是不对呀,FutureTask明明也可以作为形参构造Thread对象?聪明的你一定已经想到了,没错,FutureTask实现了Runnable接口
可为什么表达式也可以作为Thread构造函数的形参?
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
查看源码可发现,Runnable接口上有个@FunctionalInterface注解,这个注解在jdk8被用于标记一个接口,如果这个接口只包含一个抽象方法,那么这个接口就是一个函数式接口,允许使用Lambda 表达式和函数式编程特性。
Runnable和Callable的使用区别:
两者都是实现了接口,但Callable允许线程返回一个结果,可以通过FutureTask.get()获取到线程的执行结果,如果调用的时候线程还没有执行完,那么会等线程执行完后再拿到结果。
但这个过程是怎样的呢?
- 初始化
FutureTask,设置state为0
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // 值为0
}
- 执行
run()方法,修改state的值
- 获取结果
public V get() throws InterruptedException, ExecutionException {
int s = state;
// 如果线程未执行,s=0
if (s <= COMPLETING)
// 自旋等待线程执行完
s = awaitDone(false, 0L);
// 获取结果
return report(s);
}