文章目录
创建线程池的方式
1. Executors.newCachedThreadPool()
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
```
特点:
1. corePoolSize为0,核心线程数为0
2. maximumPoolSize为无限大,线程数可以无限大
3. keepAliveTime为60S,线程空闲时间超过60s会杀死
4. SynchronousQueue队列,不存储东西的阻塞队列,拥有公平和非公平
```java
public SynchronousQueue() {
this(false);
}
2.Executors.newFixedThreadPool(int nThread)
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
特点:
- corePoolSize为nThread,核心线程数为nThread
- maximumPoolSize为nThread
- keepAliveTime为0,说明没任务直接死掉
- 4.LinkedBlockingQueue 最大容量可以是integer.MAX_VALUE,会产生OOM
3.Executors.newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
特点:
- corePoolSize为1,核心线程数为1
- maximumPoolSize为1
- keepAliveTime为0,说明没任务直接死掉
- LinkedBlockingQueue 最大容量可以是integer.MAX_VALUE,会产生OOM
4. Executors.newScheduledThreadPool(int corePoolSize)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
```
特点:
1. corePoolSize可以制定
2. maximumPoolSize为1
3. keepAliveTime为0,说明没任务直接死掉,任务等待的时间
4. DelayedWorkQueue 是一个无界队列,从队列中取到期的任务执行,执行完又放回队列
```java
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay, // 首次执行的延时时间
long period, //定时执行的间隔时间
TimeUnit unit
自定义线程 ThreadPoolExecutor()
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
线程池拒绝策略
- AbortPolicy :丢弃任务并抛出 RejectedExecutionException,线程池默认拒绝策略。直接抛异常让我们及时发现程序的情况,关键任务使用
- DiscardPolicy :丢弃任务,不抛异常,无关紧要任务可以使用
- DiscardOldestPolicy:丢弃前面在队列的任务,接收拒绝的任务
- CallerRunsPolicy:给提交任务的线程执行,如主线程
- 自定义拒绝策略
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
//打印丢弃的任务
System.out.println("拒绝了" + r.toString() );
}
}
线程池五种状态
线程池用一个AtomictInteger 变量 ctl来表示线程池状态和线程池中线程个数,其中高3位表示线程状态,其余29位表示线程池的线程个数。
线程池一共有五种状态:
1. RUNNING
* 高3位为 -1
* 线程池初始化状态为RUNNING,创建就为这种状态
* 能够接收任务,运行已经接收的任务,从0开始
2. SHUTDOWN
* 高3位为 0
* 此状态下不接收新的任务,但继续处理已接收的任务
* 调用 threadPoolExecutor.shutdown(); 即可从RUNNING 变为 SHUTDOWN
3. STOP
* 高3位为 1
* 此状态不接收新的任务,也不继续处理已经接收的任务,还会中断正在处理的任务
* 调用threadPoolExecutor.shutdownNow();,从RUNNING 或者 SHUTDOWN 变为 STOP
void interruptIfStarted() {
Thread t;
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
```
4. TIDYING
* 高3位为 2
* 所有任务都终止后,ctl的线程数量都为0,则会变成此状态
*SHUTDOWN状态下,阻塞队列为空当前也没有任务在执行时就会变为TIDYING
* STOP状态下,没有任务在执行了就会变为TIDYING
5. TERMINATED
* 高3位为 3
* 线程池关闭
* TIDYING状态下,执行terminated()后变为TERMINATED
![示意图](https://img-blog.csdnimg.cn/20210707211942877.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h1aWd1aWZ1aHVv,size_16,color_FFFFFF,t_70)
# 线程复用原理
先看看Worker类
```java
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
/**
* This class will never be serialized, but we provide a
* serialVersionUID to suppress a javac warning.
*/
private static final long serialVersionUID = 6138294804551838833L;
/** Thread this worker is running in. Null if factory fails. */
final Thread thread;
/** Initial task to run. Possibly null. */
Runnable firstTask;
/** Per-thread task counter */
volatile long completedTasks;
/**
* Creates with given first task and thread from ThreadFactory.
* @param firstTask the first task (null if none)
*/
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
/** Delegates main run loop to outer runWorker */
public void run() {
runWorker(this);
}
// Lock methods
//
// The value 0 represents the unlocked state.
// The value 1 represents the locked state.
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;
}
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) {
}
}
}
}
说明:worker类包装了Runnable对象,实现了Runnable接口,重写了run方法,重写的run方法是调用runWorker(),runWorker里面有不断从阻塞队列获取Runnable对象然后调用它的run方法。Thread.start()只能调用一次,一旦这个调用结束,则该线程就到了stop状态,不能再次调用start。而run方法却可以调用多次。
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);
}
}