3.1 创建线程执行器
来源:互联网 发布:mac word文件丢失 编辑:程序博客网 时间:2024/04/30 12:27
创建线程执行器
Executor Framework概述
Java5引入了执行器框架(Executor Framework),这套框架分离了任务的创建和执行。使用执行器,仅需要实现Runnable接口的对象,然后将这些对象发送给执行器即可。执行器通过创建所需的线程,来负责这些Runnable对象的创建、实例化以及运行。而且,执行器使用了线程池来提高应用程序性能。当发送一个任务给执行器时,执行器会尝试使用线程池中的线程来执行这个任务,避免了不断地创建和销毁线程而导致系统吸能下降。
执行器的另一个重要优势是Callable接口。它类似于Runnable接口,但提供个两方面的增强:
- Callable接口的主方法是call,可以返回结果。
- 当发送一个Callable对象给执行器时,将获得一个实现了Future接口的对象。可以使用这个对象来控制Callable对象的状态和结果。
创建执行器
Executor Framework是由围绕着Executor和子接口ExecutorService的接口和类组成。主要使用的实现类是ThreadPoolExecutor类。ThreadPoolExecutor提供了4个重载的构造函数,这4个构造函数参数都比较复杂,所以一般都是通过工厂Executors的静态方法来创建。比如使用Executors的newCachedThreadPool方法创建一个缓存线程池的执行器,使用Executors.newFixedThreadPool方法创建固定大小的线程执行器。
创建缓存线程池执行器示例
下面用示例说明如何创建缓存线程池执行器:
public class CachedThreadPoolDemo { public static void main(String[] args){ ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newCachedThreadPool(); for(int i=0; i<10; i++){ DummayTask task = new DummayTask(); executor.execute(task); } executor.shutdown(); }}class DummayTask implements Runnable{ private Date initDate; DummayTask() { this.initDate = new Date(); } @Override public void run() { System.out.println(Thread.currentThread().getName() + ":任务创建时间:" + initDate); System.out.println(Thread.currentThread().getName() + ":任务开始时间:" + new Date()); long delay = (long)(Math.random()*1000); try { Thread.sleep(delay); System.out.println(Thread.currentThread().getName() + ":任务完成时间:" + new Date()); } catch (InterruptedException e) { e.printStackTrace(); } }}
程序运行日志:
pool-1-thread-2:任务创建时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-2:任务开始时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-6:任务创建时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-1:任务创建时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-4:任务创建时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-8:任务创建时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-4:任务开始时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-3:任务创建时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-3:任务开始时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-7:任务创建时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-7:任务开始时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-8:任务开始时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-5:任务创建时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-5:任务开始时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-1:任务开始时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-10:任务创建时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-10:任务开始时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-6:任务开始时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-9:任务创建时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-9:任务开始时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-5:任务完成时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-6:任务完成时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-4:任务完成时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-10:任务完成时间:Mon Apr 21 16:06:28 CST 2014pool-1-thread-3:任务完成时间:Mon Apr 21 16:06:29 CST 2014pool-1-thread-9:任务完成时间:Mon Apr 21 16:06:29 CST 2014pool-1-thread-7:任务完成时间:Mon Apr 21 16:06:29 CST 2014pool-1-thread-2:任务完成时间:Mon Apr 21 16:06:29 CST 2014pool-1-thread-8:任务完成时间:Mon Apr 21 16:06:29 CST 2014pool-1-thread-1:任务完成时间:Mon Apr 21 16:06:29 CST 2014
创建固定大小的线程执行器示例
上例显示了缓存线程池执行器的使用方法,当需要执行新任务时,缓存线程池执行器就会创建新线程来执行,只有线程所运行的任务执行完成后并且这个线程可用,才会重用这些线程。这种机制情况下,如果发给过多任务将会使系统负荷过载。为避免这个问题,可以使用固定大小的线程执行器。这个执行器有一个线程最大值,如果发送超过这个最大值的任务,执行器将不再创建额外线程,剩下的任务将被阻塞直到执行器有空闲的线程可用。这样可以保证执行器不会是系统的负荷过载。下面示例演示了固定大小的线程执行器使用方法:
public class FixedThreadPoolDemo { public static void main(String[] args){ ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(3); for(int i=0; i<10; i++){ DummayTask task = new DummayTask(); executor.execute(task); System.out.println("main:执行器线程数:" + executor.getActiveCount()); } executor.shutdown(); }}
程序运行日志:
main:执行器线程数:1main:执行器线程数:2main:执行器线程数:3main:执行器线程数:3main:执行器线程数:3main:执行器线程数:3main:执行器线程数:3main:执行器线程数:3main:执行器线程数:3main:执行器线程数:3pool-1-thread-2:任务创建时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-2:任务开始时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-3:任务创建时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-3:任务开始时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-1:任务创建时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-1:任务开始时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-1:任务完成时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-1:任务创建时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-1:任务开始时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-2:任务完成时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-2:任务创建时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-2:任务开始时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-3:任务完成时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-3:任务创建时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-3:任务开始时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-1:任务完成时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-1:任务创建时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-1:任务开始时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-3:任务完成时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-3:任务创建时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-3:任务开始时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-2:任务完成时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-2:任务创建时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-2:任务开始时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-3:任务完成时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-3:任务创建时间:Mon Apr 21 16:18:02 CST 2014pool-1-thread-3:任务开始时间:Mon Apr 21 16:18:03 CST 2014pool-1-thread-2:任务完成时间:Mon Apr 21 16:18:04 CST 2014pool-1-thread-1:任务完成时间:Mon Apr 21 16:18:04 CST 2014pool-1-thread-3:任务完成时间:Mon Apr 21 16:18:04 CST 2014
可以看出,执行器运行的线程数没有超过3个。
0 0
- 3.1 创建线程执行器
- 并发编程--创建线程执行器
- Android 创建线程执行任务
- linux 线程创建与执行
- Java7并发编程--4.1、创建线程执行器
- 线程执行器的创建:Executor及其子类
- [笔记][Java7并发编程实战手册]4.3 创建固定的线程执行器newFixedThreadPool线程池
- java线程的创建,启动,执行
- Qt 创建一个线程执行某个函数
- 【运动控制】创建线程执行缓冲区
- 线程创建后不执行问题
- 线程执行器
- 线程执行器
- java线程执行器
- 线程执行器
- java线程执行器
- boost线程库学习--(1)创建和执行线程
- Java线程学习(一)线程的创建和执行
- 12.3
- POJ 2329 (暴力+搜索bfs)
- textarea计算输入字符大小并限制输入
- 算法学习十八----寻找发帖水王
- leetcode Largest Rectangle in Histogram
- 3.1 创建线程执行器
- OpenCV_读取文件夹下的图片生成视频文件
- UML视图(五)活动图
- DELETE、TRUNCATE与高水位线(HWM)
- 《贺新郎.读史》 —— 毛泽东
- CommandName与CommandArgument
- POJ - 1475 Pushing Boxes
- storm problem
- JavaScript AOP编程 很明了的一个例子