ThreadPool技术分析
来源:互联网 发布:php 输出错误信息 编辑:程序博客网 时间:2024/06/06 10:54
ThreadPool技术分析
- ThreadPool技术分析
ThreadPool是我们进行并发开发中肯定要使用的一个强大工具,因为创建线程不仅要在VM栈分配新的线程执行栈,而且要调native方法对线程做创建和初始化,是个相当占用资源的事情。如果宿主机操作系统使用的KLT的话,不断的创建和销毁线程对程序的性能影响更加严重。
本文将以java.util.concurrent.ThreadPoolExecutor
为例,简单地分析一下ThreadPool的实现原理。
首先,我们先看看java.util.concurrent.ThreadPoolExecutor#execute
/*** Executes the given task sometime in the future. The task* may execute in a new thread or in an existing pooled thread.** If the task cannot be submitted for execution, either because this* executor has been shutdown or because its capacity has been reached,* the task is handled by the current {@code RejectedExecutionHandler}.** @param command the task to execute* @throws RejectedExecutionException at discretion of* {@code RejectedExecutionHandler}, if the task* cannot be accepted for execution* @throws NullPointerException if {@code command} is null*/public void execute(Runnable command) { if (command == null) throw new NullPointerException(); /* * Proceed in 3 steps: * * 1. If fewer than corePoolSize threads are running, try to * start a new thread with the given command as its first * task. The call to addWorker atomically checks runState and * workerCount, and so prevents false alarms that would add * threads when it shouldn't, by returning false. * * 2. If a task can be successfully queued, then we still need * to double-check whether we should have added a thread * (because existing ones died since last checking) or that * the pool shut down since entry into this method. So we * recheck state and if necessary roll back the enqueuing if * stopped, or start a new thread if there are none. * * 3. If we cannot queue task, then we try to add a new * thread. If it fails, we know we are shut down or saturated * and so reject the task. */ int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0) addWorker(null, false); } else if (!addWorker(command, false)) reject(command);}
我可以看到,实现上虽然方法名叫execute,实际上只是把Runnable对象加入了一个private final BlockingQueue<Runnable> workQueue;
, 等待被执行。
java.util.concurrent.ThreadPoolExecutor#runWorker
才是真正运行Runnable对象的方法:
/*** Main worker run loop. Repeatedly gets tasks from queue and* executes them, while coping with a number of issues:** 1. We may start out with an initial task, in which case we* don't need to get the first one. Otherwise, as long as pool is* running, we get tasks from getTask. If it returns null then the* worker exits due to changed pool state or configuration* parameters. Other exits result from exception throws in* external code, in which case completedAbruptly holds, which* usually leads processWorkerExit to replace this thread.** 2. Before running any task, the lock is acquired to prevent* other pool interrupts while the task is executing, and then we* ensure that unless pool is stopping, this thread does not have* its interrupt set.** 3. Each task run is preceded by a call to beforeExecute, which* might throw an exception, in which case we cause thread to die* (breaking loop with completedAbruptly true) without processing* the task.** 4. Assuming beforeExecute completes normally, we run the task,* gathering any of its thrown exceptions to send to afterExecute.* We separately handle RuntimeException, Error (both of which the* specs guarantee that we trap) and arbitrary Throwables.* Because we cannot rethrow Throwables within Runnable.run, we* wrap them within Errors on the way out (to the thread's* UncaughtExceptionHandler). Any thrown exception also* conservatively causes thread to die.** 5. After task.run completes, we call afterExecute, which may* also throw an exception, which will also cause thread to* die. According to JLS Sec 14.20, this exception is the one that* will be in effect even if task.run throws.** The net effect of the exception mechanics is that afterExecute* and the thread's UncaughtExceptionHandler have as accurate* information as we can provide about any problems encountered by* user code.** @param w the worker*/final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) { w.lock(); // If pool is stopping, ensure thread is interrupted; // if not, ensure thread is not interrupted. This // requires a recheck in second case to deal with // shutdownNow race while clearing interrupt if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); try { beforeExecute(wt, task); Throwable thrown = null; try { task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly); }}
可以清楚地看看,ThreadPool实际是上是java.util.concurrent.ThreadPoolExecutor.Worker
的Pool, 而不是由我们的Runnable创建的Thread组成的Pool, 同时Worker Thread明显也不会在Runnable执行完以后销毁。不过没有关系,因为Runnable的task是在local scope中执行的,其创建的对象在表现上面与在真实的单独Thread中运行一般没有什么不同,除非有与Thread相关的操作存在,比如有ThreadLocal变量。
阅读全文
0 0
- ThreadPool技术分析
- threadpool源码分析
- ThreadPool原理分析
- 一个简单的ThreadPool分析
- Java threadpool机制深入分析
- Java threadpool机制深入分析
- elasticsearch源码分析---threadpool模块
- Java threadpool机制深入分析
- mariadb 5.5 threadpool 源码分析
- Java threadpool机制深入分析
- threadpool
- ThreadPool
- threadPool
- threadpool
- ThreadPool
- threadpool
- threadpool
- ThreadPool
- SJTU OJ 1558 最长序列问题
- C++拷贝构造函数可以访问传入对象的private成员变量
- Linux中安装及常用操作命令
- SDNU__1175.开心的金明
- 关于Vue父子组件之间的通信
- ThreadPool技术分析
- 选择排序、冒泡排序、插入排序、基数排序、快速排序、归并排序完整C++实现
- 年轻人在外拼搏须记住这些话
- Hibernate面试题+答案
- Eclipse Class Decompiler
- firewalld关于service的操作
- 171201 How to install Chrome and SurfEasy on Linux
- Linux运维常用命令汇总
- Hibernate中二级缓存指的是什么?