多线程与异步

一、如何让多线程执行我们的任务

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:
image

FutureTask包装内部逻辑:
image

FutureTask内部维护Callable类型的成员变量,对于Callable任务,直接赋值即可,而对于Runnable任务,需要先调用Executors#callable()把Runnable先包装成Callable
● Callable --> 直接赋值给FutureTask内部的callable字段
● Runnable --> 通过Executors.callable(runnable) 把Runnable塞到RunnableAdapter --> 把包装后的RunnableAdapter赋值给callable字段。
image

众所周知,Callable#call()是有返回值的,而Runnable#run()没有。它们都包装成FutureTask后,一个有返回值,一个没返回值,怎么处理呢?

Runnable.run()确实没返回值,搞个假的返回即可,这一步是在RunnableAdapter做的:
image

这也是上面的程序中,FutureTask为什么要多传一个参数的原因。

补充异步回调

https://zhuanlan.zhihu.com/p/369574870

posted @ 2021-10-11 19:06  光一  阅读(23)  评论(0编辑  收藏  举报