Executor框架(转)
摘要:
Executor:一个接口,其定义了一个接收Runnable对象的方法executor,其方法签名为executor(Runnable command),
二、Executor框架的两级调度模型
从图中可以看出,该框架用来控制应用程序的上层调度(下层调度由操作系统内核控制,不受应用程序的控制)。
三、Executor框架的结构
Executor主要由三部分组成:任务产生部分,任务处理部分,结果获取部分。(设计模式:生产者与消费者模式)
先来看个图:
1.任务的产生:Runnable接口和Callable接口
2.任务的处理:Executor接口—>ExecutorService接口
任务的处理主要是将任务丢到线程池中,由线程池提供线程将任务“消费掉”。
线程池有2类:ThreadPoolExecutor和ScheduledThreadPoolExecutor。2种线程池类均可以通过工厂类Executors来创建。
⑴:ThreadPoolExecutor类
工厂类可以创建3种类型的ThreadPoolExecutor类:
①:FixedThreadPool:拥有固定数量线程的线程池,限制了线程的数目,适用于负载比较重的服务器。
②:SingleThreadPool:单个线程的线程池,适用于需要保证顺序的执行各个任务;任意时间点,不会有多个线程活动。
③:CachedThreadPool:大小无界的线程池,适用于执行很多的短期异步任务的小程序,或者是负载较轻的服务器。
⑵:ScheduleThreadPoolExecutor类
工厂类可以创建2种类型的SchedulePoolExecutor类:
①:ScheduleThreadPoolExecutor:包含若干线程。
②:SingleThreadScheduleExecutor:单个线程。
3.任务结果的获取:Future接口
四、Executors类
例子:newCachedThreadPool
/** * 运行结果:可以看出缓存线程池大小是不定值,可以需要创建不同数量的线程, * 在使用缓存型池时,先查看池中有没有以前创建的线程,如果有,就复用.如果没有,就新建新的线程加入池中, * 缓存型池子通常用于执行一些生存期很短的异步型任务 * */ public class newCachedThreadPoolTest { public static void main(String[] args) { //创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程 ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 20; i++) { Runnable syncRunnable = new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()); } }; executorService.execute(syncRunnable); } } }
console输出结果:
例子:newFixedThreadPool
/** * 运行结果:总共只会创建5个线程, 开始执行五个线程, * 当五个线程都处于活动状态,再次提交的任务都会加入队列等到其他线程运行结束,当线程处于空闲状态时会被下一个任务复用 * */ public class newFixedThreadPoolTest { public static void main(String[] args) { //Executors工厂类创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程 ExecutorService executorService = Executors.newFixedThreadPool(5); for(int i = 0; i < 20; i++) { Runnable synRunnable = new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()); } }; executorService.execute(synRunnable); } } }
console输出结果:
例子:newScheduledThreadPool
public class newScheduledThreadPoolTest { public static void main(String[] args) { //创建一个定长线程池,支持定时及周期性任务执行 ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5); for (int i = 0; i < 20; i++) { final int count = i; Runnable syncRunnable = new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + " ----- " + count); } }; //表示从提交任务开始计时,5000毫秒后执行 //运行结果和newFixedThreadPool类似,不同的是newScheduledThreadPool是延时一定时间之后才执行 executorService.schedule(syncRunnable, 5000, TimeUnit.MILLISECONDS); } } }
console输出结果:
例子:newSingleThreadExecutor
public class newSingleThreadExecutorTest { public static void main(String[] args) { //创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行 //运行结果:只会创建一个线程,当上一个执行完之后才会执行第二个 ExecutorService executorService = Executors.newSingleThreadExecutor(); for (int i = 0; i < 20; i++) { Runnable syncRunnable = new Runnable() { public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()); } }; executorService.execute(syncRunnable); } } }
console输出结果:
结合Future接口来做一个实测
public class FutureDemo { public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(3); // CompletionService接口内部维护一个结果队列:一堆future.... CompletionService<Integer> cs = new ExecutorCompletionService<>(pool); for (int i = 1; i < 11; i++) { final int flag = i * 10; cs.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { System.out.println(Thread.currentThread().getName()); Thread.sleep(1000); return flag; } }); } for (int i = 0; i < 11; i++) { try { System.out.println(cs.take().get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } pool.shutdown(); } }
console输出结果:
附录一张图来介绍Executor框架
资料出处:https://blog.csdn.net/qq_16811963/article/details/52161713
https://blog.csdn.net/qq_35794278/article/details/81481483