多线程与异步
一、如何让多线程执行我们的任务
public class AsyncAndWaitTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 方式1:重写Thread#run()
Thread thread = new Thread() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "========>正在执行");
}
};
thread.start();
// 方式2:构造方法传入Runnable实例
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "========>正在执行");
}).start();
// 方式3:线程池 + Callable/Runnable,这里以Callble为例
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> submit = executorService.submit(() -> {
System.out.println(Thread.currentThread().getName() + "========>正在执行");
Thread.sleep(3 * 1000L);
return "success";
});
String result = submit.get();
System.out.println("result=======>" + result);
// 关闭线程池
executorService.shutdown();
}
}
二、FutureTask
FutureTask = 任务 + 结果。
FutureTask包装Runnable与Callable:
FutureTask包装内部逻辑:
FutureTask内部维护Callable类型的成员变量,对于Callable任务,直接赋值即可,而对于Runnable任务,需要先调用Executors#callable()把Runnable先包装成Callable。
● Callable --> 直接赋值给FutureTask内部的callable字段
● Runnable --> 通过Executors.callable(runnable) 把Runnable塞到RunnableAdapter --> 把包装后的RunnableAdapter赋值给callable字段。
众所周知,Callable#call()是有返回值的,而Runnable#run()没有。它们都包装成FutureTask后,一个有返回值,一个没返回值,怎么处理呢?
Runnable.run()确实没返回值,搞个假的返回即可,这一步是在RunnableAdapter做的:
这也是上面的程序中,FutureTask为什么要多传一个参数的原因。