//FutureTask可用于异步获取执行结果或取消执行任务的场景
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V>
1、代码示例
public class MainTest {
public static void main(String[] args) throws Exception {
FutureTask<Integer> integerFutureTask = new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Random random = new Random();
return random.nextInt(10);
}
});
//直接调用其run方法或者放入线程池执行
//执行方式1:
integerFutureTask.run();
//执行方式2:
ExecutorService exec = Executors.newFixedThreadPool(5);
//exec.submit(integerFutureTask);
//执行方式3:
/**
List<Callable<Integer>> list = new ArrayList<>();
list.add(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Random random = new Random();
return random.nextInt(10);
}
});
List<Future<Integer>> futures = exec.invokeAll(list);
int tempCount = futures.get(0).get();
System.out.println("执行结果:" + tempCount);
*/
int count = integerFutureTask.get();
System.out.println("执行结果:" + count);
FutureTask task = new FutureTask(new Callable() {
@Override
public Object call() throws Exception {
for (int index = 1; index <= count; index++) {
System.out.println("休眠" + index + "秒");
Thread.sleep(1000);
}
return "执行完毕";
}
});
task.run();
System.out.println("执行结果:" + task.get());
}
}
2、FutureTask在高并发环境下确保任务只执行一次
确保即使调用了多次run方法,它都只会执行一次Runnable或者Callable任务。
数据库的连接池、tair的连接池都是基于FutureTask来实现的,避免了加锁带来的性能问题。
连接池Demo
public class MainTest {
private ConcurrentHashMap<String, FutureTask<Connection>>
connectionPool = new ConcurrentHashMap<>();
public static void main(String[] args) throws Exception {
MainTest mainTest = new MainTest();
Connection connection = mainTest.getConnection("");
}
public Connection getConnection(String key) throws Exception {
FutureTask<Connection> connectionTask = connectionPool.get(key);
if (connectionTask != null) {
return connectionTask.get();
} else {
Callable<Connection> callable = new Callable<Connection>() {
@Override
public Connection call() throws Exception {
return createConnection();
}
};
FutureTask<Connection> newTask = new FutureTask<>(callable);
connectionTask = connectionPool.putIfAbsent(key, newTask);
if (connectionTask == null) {
connectionTask = newTask;
connectionTask.run();
}
return connectionTask.get();
}
}
//创建Connection
private Connection createConnection() {
//todo
return null;
}
}
3、FutureTask 源码
FutureTask的get方法可以实现获取线程执行结果,或者设置超时时间获取线程执行结果 原理:
封装一个存放线程执行结果的变量A,使用AQS的独占API实现线程对变量A的独占访问。判断规则是,线程没有执行完毕:call()方法没有返回前,不能访问变量A;或者是超时时间没到前不能访问变量A。