线程池的核心是ThreadPoolExecutor。Executor、Executors、ExecutorService、AbstractExecutorService这些接口或类都是ThreadPoolExecutor的祖宗,下面分别进行阐述
一、Executor接口
在源码中Executor是一个接口,这个接口只有一个方法void execute(Runnable command)方法。该方法提供一种将任务提交与每个任务将如何运行分离开来的方法。通常使用Executor的场景并不是显式地创建线程,而是只执行任务,实现线程的创建和线程的执行解耦。
// 传统的使用方案 public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { System.out.println("新建工单消息提醒"); } }, "新建工单线程").start(); new Thread(new Runnable() { @Override public void run() { System.out.println("工单结单消息提醒"); } }, "工单结单线程").start(); } // 使用Executor接口的方案 public static void main(String[] args) { Executor executor = new ThreadPoolExecutor(5, 10, 3, TimeUnit.NANOSECONDS, null); executor.execute(new Runnable() { @Override public void run() { System.out.println("新建工单消息提醒"); } }); executor.execute(new Runnable() { @Override public void run() { System.out.println("工单结单消息提醒"); } }); }
上面代码可以看出来,不需要.start()两次,就可以创建线程出来。如此说来,个人感觉Executor更像是一个瓶起子,来一瓶啤酒,就开一瓶啤酒;不再像之前那样,为每一瓶啤酒,搞一个瓶起子。
二、ExecutorService接口
//一个接口继承另一个接口 public interface ExecutorService extends Executor{...}
接口ExecutorService补充了十二个接口。因为它是接口,所以理所当然的并没有给出Executor接口中execute()方法的实现。Executors类为创建ExecutorService提供了便捷的工厂方法。ExecutorService还蛮重要的,看看它的衍生家族吧。
//接口ScheduledExecutorService继承了接口ExecutorService public interface ScheduledExecutorService extends ExecutorService {...} //创建newCachedThreadPool,返回ExecutorService ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); //创建newFixedThreadPool,返回ExecutorService ExecutorServie fixedThreadPool = Executors.newFixedThreadPool(); //创建newSingleThreadExecutor(),返回ExecutorService ExecutorService singleThreadPool = Executors.newSingleThreadExecutor()); //创建newWorkStealingPool,返回ExecutorService ExecutoreService workStealingThreadPool = Executores.newWorkStealingPool()); //创建newScheduledThreadPool,返回ScheduledExecutorService ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool());
接口ExecutorServie中有名如其义的几个方法:submit、shutdown、invokeAll、awaitTermination。使用代码如下:
package executors; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * 网络服务的简单结构:这里线程池中的线程作为传入的请求。它使用了预先配置 */ public class TestNetworkService { } class NetworkService implements Runnable { private final ServerSocket serverSocket; private final ExecutorService threadPool; public NetworkService(int port, int poolSize) throws IOException{ this.serverSocket = new ServerSocket(port); this.threadPool = Executors.newFixedThreadPool(poolSize); } @Override public void run() { try { for (;;) { threadPool.execute(new Handler(serverSocket.accept())); } } catch (IOException e) { threadPool.shutdown(); } } public void shutdownAndAwaitTermination(ExecutorService pool) { // Disable new tasks from being submitted pool.shutdown(); try { // 等待60秒后,任务还没执行完成,就调用 shutdownNow取消所有遗留的任务 // Wait a while for existing tasks to terminate if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { pool.shutdownNow(); // Wait a while for tasks to respond to being cancelled if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { System.err.println("pool din't terminate"); } } } catch (InterruptedException e) { // (Re-)Cancel if current thread also interrupted pool.shutdownNow(); // Preserve interrupt status Thread.currentThread().interrupt(); } } } class Handler implements Runnable { private final Socket socket; public Handler(Socket socket){ super(); this.socket = socket; } @Override public void run() { // TODO {read and service request on socket} } }
三、ThreadPoolExecutor类(它是ExecutorService)的一个实现类
线程池类为java.util.concurrent.ThreadPoolExecutor,常用的构造方法为:
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
其参数的含义分别为:
1.corePoolSize,线程池维护线程的最少数量
2.maximunPoolSize,线程池维护线程的最大数量
3.keepAliveTime,线程池维护线程所允许的空闲时间
4.unit:线程池维护线程所允许的空闲时间的单位(TimeUnit.SECONDS;TimeUnit.MICROSECONDS;)
5.workQueue:线程池所使用的缓冲队列,它常用的是:java.util.concurrent.ArrayBlockingQueue。
6.handler:线程池对拒绝任务的处理策略。handler有四个选择:
ThreadPoolExecutor.AbortPolicy();抛出java.util.concurrent.RejectedExecutionException异常。
ThreadPoolExecutor.callerRunsPolicy();重复添加当前任务,它会自动重复调用execute()方法。
ThreadPoolExecutor.DiscardOldesetPolicy();抛弃旧的任务
ThreadPoolExecutor.DiscardPolicy();抛弃当前的任务
一个任务通过execute(Runnable)方法被添加到线程池,任务就是一个Runnable类型的对象,任务的执行方法就是Runnable类型对象的run()方法,当一个任务通过execute(Runnable)方法欲添加到线程池时:
如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
如果此时线程池中的数量等于corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理任务。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
如果当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
参考:
博客:http://blog.csdn.net/linghu_java/article/details/17123057
http://cuisuqiang.iteye.com/blog/2019372
http://www.cnblogs.com/dolphin0520/p/3932921.html