Runnable富稻、Callable、Future抚岗、FutureTask
一:并發(fā)編程的核心
并發(fā)編程的核心問題:分工哪怔、同步和互斥向抢。
要編寫高質(zhì)量的并發(fā)程序胚委,只需要處理好分工、同步和互斥的問題即可篷扩,同步和互斥對(duì)應(yīng)的就是管程模型。
二:Runnable枢冤、Callable铜秆、Future淹真、FutureTask
1:Runnable连茧、Callable、Future客扎、FutureTask的UML類圖
Callable與Runnable罚斗、Future、FutureTask無繼承關(guān)系针姿。
FutureTask帶了Future和Runnable的功能。
Runnable....png
2:Runnable和Callable
// JDK1.0 不接受參數(shù)绞绒、無返回值榕暇,單線程、線程池均可使用彤枢。
public interface Runnable {
public abstract void run();
}
// JDK 1.5 不接受參數(shù)、有返回值,僅供線程池使用龄砰。
public interface Callable<V> {
V call() throws Exception;
}
3:Future API
// 取消任務(wù)
boolean cancel( boolean mayInterruptIfRunning);
// 判斷任務(wù)是否已取消
boolean isCancelled();
// 判斷任務(wù)是否已結(jié)束
boolean isDone();
// 獲得任務(wù)執(zhí)行結(jié)果 ---> 阻塞方法
get();
// 獲得任務(wù)執(zhí)行結(jié)果,支持超時(shí) ---> 阻塞方法
get(long timeout, TimeUnit unit);
4:為什么要引入FutureTask式镐?為什么要讓FutureTask實(shí)現(xiàn)Runnable?
在單線程和多線程執(zhí)行Task的時(shí)候歹茶,都有獲取執(zhí)行結(jié)果的需求你弦,但是當(dāng)使用Runnable的時(shí)候,Runnable的API是拿不到返回值的禽作,因此可以用FutureTask類包裝Runnable來拿返回值。
所以:Runnable旷偿、Callable、Future幢妄、FutureTask存在的目的是為了使用更加靈活茫负。
獲取執(zhí)行結(jié)果:
- 單線程:FutureTask包裝Callable和Runnable,通過FutureTask獲取返回值朽褪。
- 多線程:?jiǎn)为?dú)使用Callable能獲取返回值,F(xiàn)utureTask包裝Callable和Runnable能獲取返回值衍锚。
5:使用示例
/**
* <p>
* Runnable嗤堰、Callable、Future踢匣、FutureTask
* </p>
*
* @author: Sunny
* @date: 2021/2/1
* @version: v1.0.0
*/
public class TaskTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 1:?jiǎn)尉€程 + Callable + FutureTask拿到返回結(jié)果
FutureTask<Integer> task = new FutureTask<Integer>(() -> {
return 1 + 1;
});
Thread t1 = new Thread(task);
t1.start();
System.out.println(task.get());
// 2:?jiǎn)尉€程 + Runnable + T result + FutureTask拿到返回結(jié)果
Account account = new Account();
FutureTask<Account> task1 = new FutureTask<Account>(() -> {
account.setName("zhangsan");
account.setAge(3);
}, account);
Thread t2 = new Thread(task1);
t2.start();
System.out.println(task1.get().getName() + " : " + task1.get().getAge());
System.out.println(account.getName() + " : " + account.getAge());
// 3:線程池 + Callable + Future拿到返回結(jié)果
ExecutorService service = Executors.newSingleThreadExecutor();
Future<Integer> future = service.submit(() -> 1 + 1);
System.out.println(future.get());
// 4:線程池 + Runnable + Future拿不到返回結(jié)果
Future<?> future1 = service.submit(() -> System.out.println(1));
// Runnable 不接受返回值离唬,因此其值為null
System.out.println(future1.get());
// 5:線程池 + Runnable + T result + Future拿到返回結(jié)果
Account account1 = new Account();
Future<Account> future2 = service.submit(() -> {
account1.setName("xiaoming");
account1.setAge(4);
}, account1);
System.out.println(future2.get().getName() + " : " + future2.get().getAge());
System.out.println(account1.getName() + " : " + account1.getAge());
service.shutdown();
}
@Data
public static class Account {
private String name;
private Integer age;
}
}