Java线程池(3)- JUC Executors 源码分析
原创
©著作权归作者所有:来自51CTO博客作者java硕哥的原创作品,请联系作者获取转载授权,否则将追究法律责任
4、JUC Executors 使用&源码分析
未完待续,写作中…
1、JUC里有几种线程池?各自的使用场景?
FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
CachedThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
SingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
static class FinalizableDelegatedExecutorService
extends DelegatedExecutorService {
FinalizableDelegatedExecutorService(ExecutorService executor) {
super(executor);
}
protected void finalize() {
super.shutdown();
}
}
4.1、简单使用线程池
public class FixedThreadPoolTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i<6; i++) {
executorService.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName());
ThreadUtils.sleep(1000);
}
});
}
}
}
ExecutorService executorService = Executors.newFixedThreadPool(3)
,创建一个拥有 固定数量线程 的线程池。
4.1.1、Executors、ExecutorService命名
我初学JUC 线程池的时候,很不能理解,为什么要用 Executors
这个命名的工具类来创建线程池? 线程池为什么还是ExecutorService
接口的实现类?
不知道大家有没有这个疑惑?
线程池的作用是干嘛的?单纯的线程池没什么意义,执行任务才是线程池存在的意义。所以从执行任务这个角度来看,使用 Executors
和 ExectutorService
两个命名就显得合情合理了!!
ThreadPoolExecutor 源码
NO.
| 项目
| 二进制
|
A
| CAPACITY
| 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
B
| ~CAPACITY
| 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
1
| RUNNING(-1)
| 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
2
| SHUTDOWN(0)
| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
3
| STOP(1)
| 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
4
| TIDYING(2)
| 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
5
| TERMINATED(3)
| 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
private static int runStateOf(int c) { return c & ~CAPACITY; }
private static int workerCountOf(int c) { return c & CAPACITY; }
int的前3位表示 状态,通过与~CAPACITY
进行与运算可以取得(~CAPACITY
的前三位为全1)
int的后29位表示 线程数量,通过与CAPACITY
进行与运算可以取得(CAPACITY
的后29位为全1)
点击参考:反码 & 为什么使用反码
java.util.concurrent.ThreadPoolExecutor#execute源码:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))// 新增工作线程
return;
c = ctl.get();
}
// 当前 "线程池处于RUNNING状态",则 "添加当前任务到任务队列"
if (isRunning(c) && workQueue.offer(commxand)) {
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);
}
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (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 {
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
⭐️ addWorker(command, true) 上面时候返回 false ?
1、JUC里有几种线程池?各自的使用场景?
1、fixed(固定数量的线程);
使用 固定数量的线程 & 无界队列 来处理你提交的任务,只有指定数量的线程来处理任务。
这些线程都处于运行中时提交任务,任务需要放入无界队列中等待处理。
2 、cached(线程数量不固定,无论来多少任务都是不停的创建线程来执行,如果线程空闲了一定的时间,就会释放掉这个线程);
3 、single(线程池里就只有一个线程)
4、scheduled(提交进去的线程,会在指定的时间过后才去执行)
最最常见的线程池就是fixed线程池,线程数量是固定的,不会超过这个数量的线程,就执行你不断提交的任务