java线程池
来源:互联网 发布:之二虫又何知 编辑:程序博客网 时间:2024/06/10 19:54
转载地址:http://blog.csdn.net/mazhimazh/article/details/19243889
线程池的框架图如下:
1、Executor任务提交接口与Executors工具类
Executor框架同java.util.concurrent.Executor接口在jdk5.0中被引入,Executor框架是一个根据一组执行策略调用,执行异步任务的框架。Executor存在的目的是提供一种将“任务提交”和"任务如何执行"分离开来的机制。定义如下:
public interface Executor { /** * Executes the given command at some time in the future. The command * may execute in a new thread, in a pooled thread, or in the calling * thread, at the discretion of the <tt>Executor</tt> implementation. * * @param command the runnable task * @throws RejectedExecutionException if this task cannot be * accepted for execution. * @throws NullPointerException if command is null */ void execute(Runnable command);}
虽然只有一个方法,但是为强大且灵活的异步任务执行框架提供了基础。它提供了一种方法将任务的提交过程和执行过程解耦开来。并用runnable表示任务,那么我们如何得到Executor对象呢?这就是接下来要介绍的Executors对象了。
Executors为Executor、ExecutorService、SchduledExecutorService、ThreadFactory和Callable类提供了一些工具方法。Executors可以方便的创建线程池。
1、newCachThreadPool:该线程池比较适合没有固定大小且比较快速就能完成的小任务。它将为每个任务创建一个线程。如果是这样子那它和直接创建线程有什么区别的呢?
看到它的第三个参数60L和第四个参数TimeUnit.SECONDE了吗?这就是关键所在,这两个参数的意思是60秒内可以复用已经创建的线程,即如果一个线程执行完任务,它会存活60S,如果这个期间没用新的任务被提交,那么这个线程会销毁。
下面是Executors中的newCachThreadPool()方法的源码:
/** * Creates a thread pool that creates new threads as needed, but * will reuse previously constructed threads when they are * available. These pools will typically improve the performance * of programs that execute many short-lived asynchronous tasks. * Calls to <tt>execute</tt> will reuse previously constructed * threads if available. If no existing thread is available, a new * thread will be created and added to the pool. Threads that have * not been used for sixty seconds are terminated and removed from * the cache. Thus, a pool that remains idle for long enough will * not consume any resources. Note that pools with similar * properties but different details (for example, timeout parameters) * may be created using {@link ThreadPoolExecutor} constructors. * * @return the newly created thread pool */ public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
2、newFixedThreadPool:使用的Thread对象的数量是有限的。如果提交的任务数量大于最大任务数。那么这些任务将排队。如果有一个线程,任务执行完,那么它将根据调度策略等待执行下一个任务。下面是Executors 中newFixedThreadPool的源码:
/** * Creates a thread pool that reuses a fixed number of threads * operating off a shared unbounded queue. At any point, at most * <tt>nThreads</tt> threads will be active processing tasks. * If additional tasks are submitted when all threads are active, * they will wait in the queue until a thread is available. * If any thread terminates due to a failure during execution * prior to shutdown, a new one will take its place if needed to * execute subsequent tasks. The threads in the pool will exist * until it is explicitly {@link ExecutorService#shutdown shutdown}. * * @param nThreads the number of threads in the pool * @return the newly created thread pool * @throws IllegalArgumentException if {@code nThreads <= 0} */ public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
3、newSingleThreadExecutor:就是线程数量为1的fixedThreadPool,如果提交了多个任务,那么这些任务将会排队。每一个任务都会在下一个任务执行之前运行结束。所有的任务都会使用相同的线程。下面是Executors中的newSingelThreadExecutor的源码:
/** * Creates an Executor that uses a single worker thread operating * off an unbounded queue. (Note however that if this single * thread terminates due to a failure during execution prior to * shutdown, a new one will take its place if needed to execute * subsequent tasks.) Tasks are guaranteed to execute * sequentially, and no more than one task will be active at any * given time. Unlike the otherwise equivalent * <tt>newFixedThreadPool(1)</tt> the returned executor is * guaranteed not to be reconfigurable to use additional threads. * * @return the newly created single-threaded Executor */ public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
4、newScheduledThreadPool:创建一个固定长度的线程池。而且以延迟或者定时的方式来执行任务。
/** * Creates a new {@code ScheduledThreadPoolExecutor} with the * given core pool size. * * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @throws IllegalArgumentException if {@code corePoolSize < 0} */ public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS, new DelayedWorkQueue()); }
通过前面的线程池的源码可以知道:
1、除了CachedThreadPool使用的是直接提交策略的队列以外。其余两个都是采用的无界缓冲队列。也就是说FixedThreadPool和SingleThreadPool创建的线程数不会大于corePoolSize;
2、三个线程池采用的ThreadPoolExecutor构造方法都是同一个,使用的都是默认的ThreadFactory和handler。
/** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters and default thread factory and rejected execution handler. * It may be more convenient to use one of the {@link Executors} factory * methods instead of this general purpose constructor. * * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param maximumPoolSize the maximum number of threads to allow in the * pool * @param keepAliveTime when the number of threads is greater than * the core, this is the maximum time that excess idle threads * will wait for new tasks before terminating. * @param unit the time unit for the {@code keepAliveTime} argument * @param workQueue the queue to use for holding tasks before they are * executed. This queue will hold only the {@code Runnable} * tasks submitted by the {@code execute} method. * @throws IllegalArgumentException if one of the following holds:<br> * {@code corePoolSize < 0}<br> * {@code keepAliveTime < 0}<br> * {@code maximumPoolSize <= 0}<br> * {@code maximumPoolSize < corePoolSize} * @throws NullPointerException if {@code workQueue} is null */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
也就是说三个线程池创建的线程对象都是同组对象。
2、ExecutorService任务周期管理接口
Executor的实现通常都会创建线程来处理任务,由于使用异步方式来执行任务时,由于之前提交的任务的状态是不能立即可以见的,如果想关闭应用程序的话,就要把受影响的任务反馈给应用程序。
为了解决执行任务的声明周期问题,ExecutorService扩展了Executor接口,添加了一个用于声明周期的管理的方法:
public interface ExecutorService extends Executor { void shutdown(); List<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; // 省略部分方法 }
3、ThreadPoolExecutor 线程池实现类:
private final BlockingQueue<Runnable> workQueue; // 阻塞队列 private final ReentrantLock mainLock = new ReentrantLock(); // 互斥锁 private final HashSet<Worker> workers = new HashSet<Worker>();// 线程集合.一个Worker对应一个线程 private final Condition termination = mainLock.newCondition();// 终止条件 private int largestPoolSize; // 线程池中线程数量曾经达到过的最大值。 private long completedTaskCount; // 已完成任务数量 private volatile ThreadFactory threadFactory; // ThreadFactory对象,用于创建线程。 private volatile RejectedExecutionHandler handler;// 拒绝策略的处理句柄 private volatile long keepAliveTime; // 线程池维护线程所允许的空闲时间 private volatile boolean allowCoreThreadTimeOut; private volatile int corePoolSize; // 线程池维护线程的最小数量,哪怕是空闲的 private volatile int maximumPoolSize; // 线程池维护的最大线程数量
其中有几个重要的规则要说明下:
1、corePoolSize和maximumPoolSize :
2、workQueue
1、直接提交
2、无界队列
3、有界队列
3、ThreadFactory
public interface ThreadFactory { Thread newThread(Runnable r); }
public static ThreadFactory defaultThreadFactory() { return new DefaultThreadFactory(); }
static class DefaultThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber = new AtomicInteger(1); private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } // 为线程池创建新的任务执行线程 public Thread newThread(Runnable r) { // 线程对应的任务是Runnable对象r Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(), 0); // 设为非守护线程 if (t.isDaemon()) t.setDaemon(false); // 将优先级设为Thread.NORM_PRIORITY if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } }
4、RejectedExecutionHandler
private static final RejectedExecutionHandler defaultHandler = new AbortPolicy(); // 使用默认的拒绝策略
public static class AbortPolicy implements RejectedExecutionHandler { public AbortPolicy() { } // 抛出异常 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); } }
下面看下其他拒绝策略的具体实现:
class MyRunnable implements Runnable { private String name; public MyRunnable(String name) { this.name = name; } @Override public void run() { try { System.out.println(this.name + " is running."); Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } } }
public class DiscardPolicyDemo {private static final int THREADS_SIZE = 1; private static final int CAPACITY = 1; public static void main(String[] args) {//创建线程池,线程池ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(CAPACITY));//设置线程池的拒绝策略为丢弃策略pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());for (int i = 0; i < 10; i++) {MyRunnable mr = new MyRunnable("task_" + i);pool.execute(mr);}pool.shutdown();} }
task_0 is running.task_1 is running.
线程池的“最大线程池大小”和“线程池核心大小”都是1(THREADS_SIZE),这意味着线程池能同时运行的任务数量最大只能是1。
public class DiscardOldestPolicyDemo {private static final int THREADS_SIZE = 1; private static final int CAPACITY = 1; public static void main(String[] args) {//创建线程池,线程池ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(CAPACITY));//设置线程池的拒绝策略为丢弃策略pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());for (int i = 0; i < 10; i++) {MyRunnable mr = new MyRunnable("task_" + i);pool.execute(mr);}pool.shutdown();}}
运行结果:
task_0 is running.task_9 is running.
public class AbortPolicyDemo {private static final int THREADS_SIZE = 1; private static final int CAPACITY = 2; public static void main(String[] args) {//创建线程池,线程池ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(CAPACITY));//设置线程池的拒绝策略为丢弃策略pool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());for (int i = 0; i < 10; i++) {MyRunnable mr = new MyRunnable("task_" + i);pool.execute(mr);}pool.shutdown();}}
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.threadpool.kw.MyRunnable@3dc0bb rejected from java.util.concurrent.ThreadPoolExecutor@384065[Running, pool size = 1, active threads = 1, queued tasks = 2, completed tasks = 0]at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(Unknown Source)at java.util.concurrent.ThreadPoolExecutor.reject(Unknown Source)at java.util.concurrent.ThreadPoolExecutor.execute(Unknown Source)at com.threadpool.kw.AbortPolicyDemo.main(AbortPolicyDemo.java:25)task_0 is running.task_1 is running.task_2 is running.
public class CallerRunPolicyDemo {private static final int THREADS_SIZE = 1; private static final int CAPACITY = 1; public static void main(String[] args) {//创建线程池,线程池ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(CAPACITY));//设置线程池的拒绝策略为丢弃策略pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());for (int i = 0; i < 10; i++) {MyRunnable mr = new MyRunnable("task_" + i);pool.execute(mr);}pool.shutdown();}}
- Java线程:线程池
- java--线程--线程池
- Java线程(六):线程池
- Java线程(五):线程池
- Java线程(五):线程池
- Java线程_07_线程池
- Java线程(五):线程池
- Java线程(六):线程池
- Java线程(五):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(六):线程池
- Java线程(五):线程池
- Java线程(六):线程池
- Intermediate perl 总结提高
- lua学习笔记_注释、基本数据类型、if语句
- SAT阅读填空题常考单词整理(3)
- C#获取本地连接IP地址
- [Java]LeetCode5 Longest Palindromic Substring
- java线程池
- Hadoop权威指南第七章
- linux获取系统时间
- linux下用vim编写C/C++单个源程序的基本方法
- 将VS项目提交至SVN时,怎样忽略bin和obj目录中的文件
- MySQL优化之——简单语法
- Android基础之使用Fragment控制切换多个页面
- 可访问的google的ip地址
- sql:除非另外还指定了 TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询