标签:
当一个服务器完成一项任务所需时间为:T1 创建线程的时间,T2 在线程中执行任务的时间,T3 销毁线程时间。若 T1+T3 > T2 时,则一般可以采用线程池。
shutdown();shutdownNow();submit();invokeAll();invokeAny();
execute();shutdown();shutdownNow();isTerminated();
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
无界队列:LinkedBlockingQueue-可无限制的增加,它是 newFixedThreadPool 和 newSingleThreadExecutor 默认的任务队列有界队列:ArrayBlockingQueue、有界的 LinkedBlockingQueue、PriorityBlockingQueue-当队列满后,会执行饱和策略同步移交:在线程之间移交的一种机制,当线程池是无界的或者是可以拒绝任务的就可以使用,newCachedThreadPool就使用的是 SynchronousQueue
ThredPoolExecutor 类中的4个静态内部类:AbortPolicy: 默认的 Handler,该策略会抛出 未检查的 RegectedExecutionExceptionCallerRunsPolicy:调用者运行,将某些任务回退到调用者(一般为主线程),由于执行任务需要一定的时间,因此主线程至少在一段时间内不能提交任何任务,从而使得工作者线程有时间来处理正在执行的任务DiscardPolicy:抛弃新提交的任务DiscardOldestPolicy:将抛弃下一个将要执行的任务
/**1.当线程池中的数目小于 corePoolSize时,直接new 一个 Thread2.当线程池数大于corePoolSize 时,直接放入 任务队列中3.如果队列已经满了且线程池中线程数小于 maximumPoolSize,则新建一个线程*/public void execute(Runnable command) {if (command == null)throw new NullPointerException();int c = ctl.get();//如果正在运行的线程数小于线程池预设的大小,就尝试addWorker(源码在其后)。若成功,直接返回。若添加失败(可能在添加过程中已达到预设的线程池的数目),重新获取线程池正在运行的线程数if (workerCountOf(c) < corePoolSize) {if (addWorker(command, true))return;c = ctl.get();}//若任务没有线程处理(当达到了线程池的预设大小 corePoolSize),就添加到任务队列。if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();if (! isRunning(recheck) && remove(command)) //若线程池在workeQueue.offer前发生了shutdown,就从任务队列中移除reject(command);else if (workerCountOf(recheck) == 0) //如果线程池在运行,并且没有可工作的线程,就直接创建一个addWorker(null, false);}else if (!addWorker(command, false)) // 如果任务队列已满,尝试创建一个新的Worker,若失败,说明线程池已经关闭 或者 饱和了reject(command); //饱和策略问题}
/**@param firstTask : 是新线程应该运行的第一个任务,Worker 会被创建 在线程池的数目 比 corePoolSize 小的时候,或者在任务队列已经满的情况下,创建一个线程来代替已死的线程@param core : 当为true时,用 corePoolSize作为边界,否则,用 maximumPoolSize 作为边界*/private boolean addWorker(Runnable firstTask, boolean core) {retry:for (;;) {int c = ctl.get();int rs = runStateOf(c); //获取线程池的状态// 如果线程池被 shutdown了,一般直接返回false。但是排除 任务队列不为空 但 Workers 为空的情况,在这种情况下,会调用 addWorker(null,false) 来创建一个线程处理队列中的任务if (rs >= SHUTDOWN &&! (rs == SHUTDOWN &&firstTask == null &&! workQueue.isEmpty()))return false;for (;;) {//如果正在执行的线程数目大于 线程池中预设的线程数,返回falseint wc = workerCountOf(c);if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize))return false;if (compareAndIncrementWorkerCount(c))break retry;c = ctl.get(); // Re-read ctlif (runStateOf(c) != rs)continue retry;// else CAS failed due to workerCount change; retry inner loop}}boolean workerStarted = false;boolean workerAdded = false;Worker w = null;try {final ReentrantLock mainLock = this.mainLock;w = new Worker(firstTask);//创建 Worker:其中Thread通过调用ThreadFactory 的 newThread 方法构建,所以在此处可以对创建的Thread进行额外的处理final Thread t = w.thread;if (t != null) {mainLock.lock();try {int c = ctl.get();int rs = runStateOf(c);//若线程池正在运行 或者 处于 shutdown 但是任务不为空,则把新建的worker添加在workers 中if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) {if (t.isAlive()) // precheck that t is startablethrow new IllegalThreadStateException();workers.add(w);int s = workers.size(); //largePoolSize 用于记录曾经出现过得最大的线程数if (s > largestPoolSize)largestPoolSize = s;workerAdded = true;}} finally {mainLock.unlock();}if (workerAdded) {//启动任务的执行t.start();workerStarted = true;}}} finally {if (! workerStarted)addWorkerFailed(w);//若启动失败,则从正在运行的工作集中移除}return workerStarted;}
/**当 线程池 被 stop 或者 shutdown 或创建线程失败时,则会调用这个方法1.从 workers 中移除 worker2.把workerCount -13.尝试终止操作:当 线程池的状态为 shutdown 、线程池的数目 和 任务队列都为空,或者线程池已经 stop 、线程池数目为0*/private void addWorkerFailed(Worker w) {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {if (w != null)workers.remove(w);decrementWorkerCount();tryTerminate();} finally {mainLock.unlock();}}
final void tryTerminate() {for (;;) {int c = ctl.get();if (isRunning(c) ||runStateAtLeast(c, TIDYING) ||(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))return;if (workerCountOf(c) != 0) { // Eligible to terminateinterruptIdleWorkers(ONLY_ONE);return; }final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {try {terminated();} finally {ctl.set(ctlOf(TERMINATED, 0));termination.signalAll();}return;}} finally {mainLock.unlock();}// else retry on failed CAS}}
个人觉得还比较重要的一个内部类是 Worker,继承了AbstractQueuedSynchronizer 类,其中最主要的 run 方法private final class Workerextends AbstractQueuedSynchronizerimplements Runnable{Worker(Runnable firstTask) {setState(-1); // inhibit interrupts until runWorkerthis.firstTask = firstTask;this.thread = getThreadFactory().newThread(this);}public void run() {runWorker(this);}protected boolean isHeldExclusively() {return getState() != 0;}protected boolean tryAcquire(int unused) {if (compareAndSetState(0, 1)) {setExclusiveOwnerThread(Thread.currentThread());return true; }return false;}protected boolean tryRelease(int unused) {setExclusiveOwnerThread(null);setState(0);return true; }// 参数 1 就是把锁设置为了独占锁,在获取到一个任务后,准备执行前首先要获取这个锁。public void lock() { acquire(1); }public boolean tryLock() { return tryAcquire(1); }public void unlock() { release(1); }public boolean isLocked() { return isHeldExclusively(); }void interruptIfStarted() {Thread t;if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {try {t.interrupt();} catch (SecurityException ignore) {}}}}
final void runWorker(Worker w) {Thread wt = Thread.currentThread();// 不从 任务队列 中获取第一个任务,而是执行刚提交的任务Runnable task = w.firstTask;w.firstTask = null;w.unlock(); // allow interruptsboolean completedAbruptly = true;try {while (task != null || (task = getTask()) != null) {w.lock();// 如果线程池是 STOP 状态,则需要保证线程时被中断了// if not, ensure thread is not interrupted. This // requires a recheck in second case to deal with // shutdownNow race while clearing interruptif ((runStateAtLeast(ctl.get(), STOP) ||(Thread.interrupted() &&runStateAtLeast(ctl.get(), STOP))) &&!wt.isInterrupted())wt.interrupt();try {beforeExecute(wt, task); // 执行前的勾子函数,可以通过重写的方式对这个函数进行扩展功能。当发生了异常时,是不会执行任务的,afterExecute 也不会执行Throwable thrown = null;try {task.run(); // 执行任务} catch (RuntimeException x) { //当发生运行时异常 或 ERROR 时,会原样抛出thrown = x; throw x;} catch (Error x) {thrown = x; throw x;} catch (Throwable x) { // 如果是一个 Throwable ,则会包装成一个 Error 抛出thrown = x; throw new Error(x);} finally {afterExecute(task, thrown); // 执行后的勾子函数,同样可以进行扩展}} finally {task = null;w.completedTasks++;w.unlock();}}completedAbruptly = false;} finally {processWorkerExit(w, completedAbruptly);}}~
/**从任务队列中获取一个任务,在以下情况会退出:1.线程数 大于 maximumPoolSize,我也不知道为什么会大于??创建的时候就会判断啊??2.线程池 已经停止3.线程池 shutdown 并且 队列 也为空4.获取一个task,超时@return : 返回一个 task ,或者worker 退出,workerCount -1*/private Runnable getTask() {boolean timedOut = false; // Did the last poll() time out?retry:for (;;) {int c = ctl.get();int rs = runStateOf(c);// 如果当前线程池已经 shutdown 或者 stop && 任务队列为空,则workerCount - 1if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {decrementWorkerCount();return null; }boolean timed; // Are workers subject to culling?for (;;) {int wc = workerCountOf(c);timed = allowCoreThreadTimeOut || wc > corePoolSize;if (wc <= maximumPoolSize && ! (timedOut && timed)) //若没有超时break;if (compareAndDecrementWorkerCount(c))return null;c = ctl.get(); // Re-read ctlif (runStateOf(c) != rs)continue retry;// else CAS failed due to workerCount change; retry inner loop}try {Runnable r = timed ?workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :workQueue.take();if (r != null)return r;timedOut = true; //若没有获取到 task ,超时} catch (InterruptedException retry) { // 若被中断了,不能算作超时timedOut = false;}}}
参考资料:
http://ifeve.com/java-threadpool/
http://blog.163.com/among_1985/blog/static/275005232012618849266/
http://developer.51cto.com/art/201203/321885.htm
http://www.51itong.net/java-1-7-threadpoolexecutor-19428.html
http://blog.csdn.net/java2000_wl/article/details/22097059
http://blog.csdn.net/xieyuooo/article/details/8718741
标签:
原文地址:http://blog.csdn.net/followmyinclinations/article/details/51693164