JUC学习-16-浅谈Callable和FutureTask

JUC学习-16-浅谈Callable和FutureTask

一、一般情况下,使用Runnbale接口、Thread实现的线程 我们都是无法返回结果的。但是如果对一些场合需要线程返回结果,就要使用CallableFuture这几个类。Callable只能在ExecutorService的线程池中跑,但有返回结果,也可以通过返回的Future对象查询执行状态。

二、Future本身也是一种设计模式,它是用来取得异步任务的结果

看看其源码:

image

Callable类中只有一个call方法,并且有一个返回V,是泛型。可以认为这里返回V就是线程返回的结果。

@FunctionalInterface // 函数式接
public interface Callable<V> {
	/**
	 * Computes a result, or throws an exception if unable to do so.
	 *
	 * @return computed result
	 * @throws Exception if unable to compute a result
	 */
	V call() throws Exception;
}

三、一般通过使用FutureTask类来包装Callable对象,然后将FutureTask对象作为参数传递给Thread

public class CallableTest {
	public static void main(String[] args) {
/*        // 第一步 创建Callable实现类的实例,并实现call方法
		class Task implements Callable<Integer> {
			@Override
			public Integer call() throws Exception {
				return 5;
			}
		}
		// 第二步 创建Callable实现类实例
		Task task = new Task();
	}*/

		// 第三步 使用FutureTask类包装Callable对象,可以创建匿名对象
		// 也可以直接使用lambda表达式 从而省略1 2 步骤
		FutureTask<Integer> future = new FutureTask(() -> {
			System.out.println("2.子线程运行中...");
			return 5;
		});
		// 第四步 使用Future Task对象作为 Thread对象的target创建、并启动新线程
		new Thread(future).start();
		System.out.println("1.已启动...");
		try {
			// FutureTask的get()方法会自动阻塞,直到得到任务执行结果位置
			Integer value = future.get();// 第五步 调用FutureTask对象的方法来回去子线程执行结束后的返回值
			System.out.println("3.返回值" + value);
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		} catch (ExecutionException e) {
			throw new RuntimeException(e);
		}
	}
}

返回结果:

image

结论:当主线程执行start()方法后开启子线程,此时主线程是异步调用,会继续往下执行。当执行到future.get()后,会查看子线程是否执行完毕(返回值)。如果未执行完毕会阻塞等待,主线程获取到子线程的返回值后 才会继续向下执行。

posted @ 2025-07-14 10:20  skystrivegao  阅读(8)  评论(0)    收藏  举报