Runnable是不能直接获取子线程运行的结果的,而Callable可以获取,一般有两种使用方式,一种是Callable+Future,另一种是Callable+FutureTask。
Future和FutureTask的用法区别是:
Future需要去接收线程池submit的结果;
FutureTask不需要去接收submit的结果,甚至都不需要threadPool.submit,threadPool.execute也可以。
下面给出自己的一个使用FutureTask的Demo。
下午小明想去运动,晚上想吃外卖 static class WaiMai{}
,外卖需要等商家制作骑手去接单送单时间不固定 long waitTime=waimai.hashCode()%5000;
,于是在运动前随机下单了外卖 DianWaiMai dianWaiMai=new DianWaiMai(new WaiMai());
,想着运动完时间差不多能吃上美味的外卖。
运动完后,小明看了看宿舍传达室的外卖桌,会有以下几种可能:
①哦豁,外卖已经到了,直接开始,可没想到外卖的分量是随机的 (System.currentTimeMillis()&1)==1
,没吃饱的话就只能再去食堂吃一点
②外卖还没到,那就再等等吧。等了一会外卖还没来,取消订单吃食堂去。
③外卖还没到,那就再等等吧。等了一会外卖来了,开吃,量不够的话还是要去食堂吃。
public class MyCallable {
static class WaiMai{}
static class DianWaiMai implements Callable<Boolean>{
private WaiMai waimai;
DianWaiMai(WaiMai waimai){
this.waimai=waimai;
}
@Override
public Boolean call() throws Exception {
long waitTime=waimai.hashCode()%5000;
Thread.sleep(waitTime);
return (System.currentTimeMillis()&1)==1;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService threadPool=Executors.newFixedThreadPool(2);
DianWaiMai dianWaiMai=new DianWaiMai(new WaiMai());
FutureTask<Boolean> futureTask=new FutureTask(dianWaiMai);
System.out.println(System.currentTimeMillis()+" 下单外卖,并且去运动");
threadPool.execute(futureTask);
Thread.sleep(2000);
System.out.println(System.currentTimeMillis()+" 运动结束,看看外卖到了没");
if(!futureTask.isDone()){
System.out.println(System.currentTimeMillis()+" 外卖还没到,在等等吧");
Thread.sleep(1000);
if(!futureTask.isDone()){
System.out.println(System.currentTimeMillis()+" 妈的外卖还没到,取消,吃食堂去");
futureTask.cancel(false);
}
}
if(!futureTask.isCancelled()) {
Boolean res = futureTask.get();
System.out.println(System.currentTimeMillis() + " 外卖到了");
if(res){
System.out.println("太多了吃撑了");
}else{
System.out.println("太少了,不够吃,再去食堂吃一点");
}
}
threadPool.shutdown();
}
}
运行结果: