/**
* 总结,
* 简单区别:返回值/异常,是否FutureTask启动(Callable接口需要,Runnable不需要)
* 注意点:futureTask启动Callable接口,futureTask获取结果会阻塞,一个FutureTask存在缓存,不用FutureTask直接Runnable接口启动没有缓存
*/
public class CallableAndRunable {
//启动Callable接口只能通过futureTask来作为适配类
public static void main(String[] args) throws ExecutionException, InterruptedException {
//线程启动的方式
// new Thread().start();//默认只能传入Runnable
// new Thread().start(new FutureTask<>(new Runnable,result));//因为FutureTask里面可以塞Runnable/Callable,所以可以通过这个适配类启动
// new Thread().start(new FutureTask<>(new Callable));
//如何通过futureTask启动Callable,
FutureTask futureTask = new FutureTask(new myThread());
new Thread(futureTask).start();
new Thread(futureTask).start();
//callable的返回结果,注意此操作可能阻塞,最好放在最后或者通过异步来操作
futureTask.get();//注意多个线程启动对同一个futureTask的操作会有缓存;(只输出一次)
//Runnable通过FutureTask启动有缓存吗?
FutureTask futureTask1 = new FutureTask(new myThread2(),"结果");
new Thread(futureTask1).start();
new Thread(futureTask1).start();//同样有缓存的。
System.out.println(futureTask1.get());
//不用FutureTask还有缓存吗?没有
new Thread(new myThread2()).start();
new Thread(new myThread2()).start();
}
}
class myThread implements Callable<String> {
//callable可以抛出异常和返参,返参由Callable接口的泛型决定
@Override
public String call() throws Exception {
System.out.println("发生肾么事了");
return "发生肾么事了";
}
}
class myThread2 implements Runnable {
@Override
public void run() {
System.out.println("Runnable一次");
return;
}
}
打印的结果:
发生肾么事了
Runnable一次
结果
Runnable一次
Runnable一次