文章目錄
線程池原理
所謂線程池,通俗的講就是有一個池子,裏面存放着已經創建好的線程,當有任務提交到池子中時,池子中的某個線程會自動執行任務,如果池子中的線程數量不夠,
則會創建更多的線程來完成任務,但是該數量是有限的。但是該數量是有限的。當任務較少時,如果池子中的線程數量不夠能夠自動回收。爲了能夠緩存沒有被完成的
任務和異步提交任務,需要一個任務隊列。
通過上面描述可知,一個完整的線程池需要以下參數:
- 任務隊列:用於緩存提交的任務。
- 線程數量管理功能,有三個參數,最大線程數maxSize,初始化線程數initSize,核心線程數coreSize,它們之間的關係是initSize<=coreSize<=maxSize。
- 拒絕策略:當線程數量已經達到上限且任務隊列已滿,這個時候要有一定的策略來通知任務提交者。
- QueueSize:主要是用來存放提交的Runnable,但是要有一個limit限制,防止內存溢出。
- KeepAlive:線程參數的自動維護時間,也就是說達到maxSize的時候,間隔多長時間恢復到coreSize。
線程池接口定義
ThreadPool
public interface ThreadPool {
/**
* 提交任務到線程池
*/
void execute(Runnable runnable);
/**
* 關閉線程池
*/
void shutdown();
/**
* 獲取初始化線程數
*/
int getInitSize();
/**
* 獲取核心線程數
*/
int getCoreSize();
/**
* 獲取最大線程數
*/
int getMaxSize();
/**
* 獲取阻塞隊列最大長度
*/
int getQueueSize();
/**
* 獲取線程池中活躍線程的數量
*/
int getActiveCount();
/**
* 查看線程池是否已經shutdown
*/
boolean isShutDown();
}
RunnableQueue
該queue是一個BlockingQueue,並且有limit限制
public interface RunnableQueue {
/**
* 當任務到coreSize時,會放到隊列上去
*/
void offer(Runnable runnable);
/**
* 獲取任務
*/
Runnable take();
/**
* 獲取任務數
*/
int size();
}
ThreadPoolFactory
個性化定製thread,比如Thread應該放到那個ThreadGroup中,優先級、線程名字、是否守護線程。
@FunctionalInterface
public interface ThreadPoolFactory {
Thread createThread(Runnable runnable);
}
DenyPolicy
當RunnableQueue的數量達到limit上限時,應該有拒絕策略通知任務提交者。
@FunctionalInterface
public interface DenyPolicy {
void reject(Runnable runnable, ThreadPool threadPool);
class DiscardDenyPolicy implements DenyPolicy {
@Override
public void reject(Runnable runnable, ThreadPool threadPool) {
// do nothing
}
}
class AbortDenyPolicy implements DenyPolicy {
@Override
public void reject(Runnable runnable, ThreadPool threadPool) {
throw new RuntimeException("The runnable:" + runnable +"will be abort.");
}
}
class RunnerDenyPolicy implements DenyPolicy {
@Override
public void reject(Runnable runnable, ThreadPool threadPool) {
if (!threadPool.isShutDown()) {
runnable.run();
}
}
}
}
-
DiscardDenyPolicy,任何事情都不做,丟棄掉
-
AbortDenyPolicy,拋出異常
-
RunnerDenyPolicy,使用調用者線程執行
InternalTask
該類實現Runnable接口,不斷從RunnableQueue上取出數據
public class InternalTask implements Runnable {
private final RunnableQueue runnableQueue;
private volatile boolean running = true;
InternalTask(RunnableQueue runnableQueue) {
this.runnableQueue = runnableQueue;
}
@Override
public void run() {
//當前任務狀態爲running並且沒有被中斷,則其不斷從queue中獲取runnable,然後執行run方法
while (running && !Thread.currentThread().isInterrupted()) {
try {
Runnable runnable = runnableQueue.take();
runnable.run();
} catch (Exception e) {
running = false;
break;
}
}
}
public void stop() {
this.running = false;
}
}
線程池自定義詳細實現
LinkedRunnableQueue
public class LinkedRunnableQueue implements RunnableQueue {
private final int limit;
private final DenyPolicy denyPolicy;
private final LinkedList<Runnable> runnableList = new LinkedList<>();
private final ThreadPool threadPool;
public LinkedRunnableQueue(int limit, DenyPolicy denyPolicy, ThreadPool threadPool) {
this.limit = limit;
this.denyPolicy = denyPolicy;
this.threadPool = threadPool;
}
@Override
public void offer(Runnable runnable) {
synchronized (runnableList) {
if (runnableList.size() >= limit) {
//無法容納新任務時,執行拒絕策略
denyPolicy.reject(runnable, threadPool);
} else {
//將任務加入隊尾,並且喚醒阻塞中的線程
runnableList.add(runnable);
runnableList.notifyAll();
}
}
}
@Override
public Runnable take() {
synchronized (runnableList) {
while (runnableList.isEmpty()) {
try {
//如果
runnableList.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return runnableList.removeFirst();
}
@Override
public int size() {
synchronized (runnableList) {
return runnableList.size();
}
}
}
-
offer方法,重要的屬性limit,這個就是隊列的上限,當觸達上限時,就會觸發拒絕策略。
-
take方法也是同步方法,線程不斷從runnableList獲取,沒有就阻塞。
-
size方法,返回隊列中的任務個數。
初始化任務線程池
BasicThreadPool
public class BasicThreadPool extends Thread implements ThreadPool {
private final int initSize;
private final int coreSize;
private final int maxSize;
private int activeCount;
private final ThreadPoolFactory threadPoolFactory;
private final RunnableQueue runnableQueue;
private volatile boolean isShutdown = false;
private final Queue<ThreadTask> threadQueue = new ArrayDeque<>();
private final static ThreadPoolFactory DEFAULT_THREAD_POOL_FACTORY = new DefaultThreadPoolFactory();
private final static DenyPolicy DEFAULT_DENY_POLICY = new DiscardDenyPolicy();
private final long keepAliveTime;
private final TimeUnit timeUnit;
public BasicThreadPool(int initSize, int coreSize, int maxSize, int queueSize) {
this(initSize, coreSize, maxSize, DEFAULT_THREAD_POOL_FACTORY, DEFAULT_DENY_POLICY, 10, TimeUnit.SECONDS,
queueSize);
}
public BasicThreadPool(int initSize, int coreSize, int maxSize, ThreadPoolFactory threadPoolFactory,
DenyPolicy denyPolicy, long keepAliveTime, TimeUnit timeUnit, int queueSize) {
this.initSize = initSize;
this.coreSize = coreSize;
this.maxSize = maxSize;
this.threadPoolFactory = threadPoolFactory;
this.runnableQueue = new LinkedRunnableQueue(queueSize, denyPolicy, this);
this.keepAliveTime = keepAliveTime;
this.timeUnit = timeUnit;
this.init();
}
private void init() {
this.start();
for (int i = 0; i < initSize; i++) {
newThread();
}
}
private void newThread() {
InternalTask internalTask = new InternalTask(runnableQueue);
Thread thread = this.threadPoolFactory.createThread(internalTask);
ThreadTask threadTask = new ThreadTask(internalTask, thread);
threadQueue.offer(threadTask);
this.activeCount++;
thread.start();
}
@Override
public void execute(Runnable runnable) {
if (this.isShutdown) {
throw new IllegalStateException("the thread pool is down.");
}
this.runnableQueue.offer(runnable);
}
@Override
public void run() {
while (!this.isShutdown && !this.isInterrupted()) {
try {
timeUnit.sleep(keepAliveTime);
} catch (InterruptedException e) {
isShutdown = true;
break;
}
//如果當前隊列有尚未執行的任務,並且小於coreSize,將隊列擴展到coreSize
if (runnableQueue.size() > 0 && activeCount < coreSize) {
for (int i = initSize; i < coreSize; i++) {
newThread();
}
continue;//不能一下擴容到maxSize
}
//如果當前隊列有尚未執行的任務,並且小於maxSize,將隊列擴展到maxSize
if (runnableQueue.size() > 0 && activeCount < maxSize) {
for (int i = coreSize; i < maxSize; i++) {
newThread();
}
}
//隊列沒有任務,
if (runnableQueue.size() == 0 && activeCount > maxSize) {
for (int i = maxSize; i < activeCount; i++) {
removeThread();
}
}
}
}
@Override
public void shutdown() {
synchronized (this) {
if (isShutdown) {
return;
}
threadQueue.forEach(threadTask -> {
threadTask.internalTask.stop();
threadTask.thread.interrupt();
});
this.interrupt();
}
}
@Override
public int getInitSize() {
return this.initSize;
}
@Override
public int getCoreSize() {
return this.coreSize;
}
@Override
public int getMaxSize() {
return this.maxSize;
}
@Override
public int getQueueSize() {
return this.runnableQueue.size();
}
@Override
public int getActiveCount() {
synchronized (this) {
return this.activeCount;
}
}
@Override
public boolean isShutDown() {
return false;
}
private void removeThread() {
ThreadTask threadTask = threadQueue.remove();
threadTask.internalTask.stop();
this.activeCount--;
}
public static class ThreadTask {
InternalTask internalTask;
Thread thread;
ThreadTask(InternalTask internalTask, Thread thread) {
this.thread = thread;
this.internalTask = internalTask;
}
}
}
- Queue用來存放活動線程,它在初始化侯,在keepAlive之後會自動維護線程池中線程數量。
- 如果當前隊列有尚未執行的任務,並且小於coreSize,將隊列擴展到coreSize,這裏使用continue終止。
- 如果當前隊列有尚未執行的任務,並且小於maxSize,將隊列擴展到maxSize。
- 隊列沒有任務,應該釋放線程中線程的數量。
ThreadPoolTest
public class ThreadPoolTest {
public static void main(String[] args) {
ThreadPool threadPool = new BasicThreadPool(2, 4, 6, 1000);
for (int i = 0; i < 20; i++) {
threadPool.execute(() -> {
try {
TimeUnit.SECONDS.sleep(10);
System.out.println("Current thread is down:" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
for (; ; ) {
System.out.println("getActiveCount-----" + threadPool.getActiveCount());
System.out.println("getInitSize-----" + threadPool.getInitSize());
System.out.println("getCoreSize-----" + threadPool.getCoreSize());
System.out.println("getMaxSize-----" + threadPool.getMaxSize());
System.out.println("getQueueSize-----" + threadPool.getQueueSize());
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}