转载文章:https://www.cnblogs.com/myxcf/p/9959870.html
Java通过Executors提供四种线程池
1).newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2).newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3).newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
4).newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
在多线程的开发中往往会遇到这种情况:主线程需要知道子线程的运行结果,以便确定如何执行任务.JDK1.5以后就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。
步骤:
1)任务类实现Callable接口
2)创建线程池:ExecutorService es = Executors.newCachedThreadPool();
3)执行任务:ChuJu cj = new ChuJu();Future future = es.submit(cj);
4)获取子线程中任务的执行结果:future.get()
下面通过实例简单说下其用法:
场景:假如你想做饭,但是没有厨具,也没有食材。网上购买厨具比较方便,食材去超市买更放心,即买出具、买食材,这两个任务异步执行,买好后才能去做饭。
创建一个com.tencent.baosen.callable.LearnCallable测试类:
package com.tencent.baosen.callable;
import java.util.concurrent.*;
//买厨具的类,实现Callable接口
class ChuJu implements Callable<Boolean> {
@Override
public Boolean call() {
try{
System.out.println("A开始去买厨具");
Thread.sleep(3000);
System.out.println("A买好厨具回来了!");
}catch (InterruptedException e){
e.printStackTrace();
}
return true;
}
}
//买食材的类,实现Callable接口
class ShiCai implements Callable<Boolean>{
@Override
public Boolean call() {
try{
System.out.println("B开始去买食材");
Thread.sleep(2000);
System.out.println("B买好食材回来了");
}catch(InterruptedException e){
e.printStackTrace();
}
return true;
}
}
//做饭的类,实现Callable接口
class ZuoFan implements Callable<Boolean>{
@Override
public Boolean call() {
try{
System.out.println("开始做饭");
Thread.sleep(5000);
System.out.println("已做好饭,可以吃饭了。");
}catch (InterruptedException e){
e.printStackTrace();
}
return true;
}
}
public class LearnCallable {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
ChuJu cj = new ChuJu();
ShiCai sc = new ShiCai();
Future<Boolean> f1 = es.submit(cj);
Future<Boolean> f2 = es.submit(sc);
try{
Boolean b1 = f1.get();//会阻塞当前线程
Boolean b2 = f2.get();
System.out.println("A的事情是否做完了:"+b1);
System.out.println("B的事情是否做完了:"+b2);
if(b1 && b2){
ZuoFan zf = new ZuoFan();
es.submit(zf);
}
}catch(Exception e){
e.printStackTrace();
}
es.shutdown();
}
}
运行结果:
A开始去买厨具
B开始去买食材
B买好食材回来了
A买好厨具回来了!
A的事情是否做完了:true
B的事情是否做完了:true
开始做饭
已做好饭,可以吃饭了。
从运行结果可以看出,买出具代码和买食材代码是异步执行的,这两个都执行完毕后,才执行的做饭代码。那么为什么子线程zuofan没有先执行呢?由于Future的get()方法没有得到返回值,让当前线程暂时挂起了。
注意:Future的get()方法,如果拿不到结果会阻塞当前线程。