一、ThreadPool原理
- 所谓线程池,通俗的理解就是有一个池子,里面存放着已经创建好的线程,当有任务提交给线程池执行时,池子中的某个线程会主动执行该任务力如果池子中的线程数量不够应付数量众多的任务时,则需要自动扩充新的线程到池子中,但是该数量是有限的,就好比池塘的水界线一样。当任务比较少的时候,池子中的线程能够自动回收,释放资源。为了能够异步地提交任务和缓存未被处理的任务,需要有一个任务队列,如图8.1所示。通过上面的描述可知,一个完整的线程池应该具备如下要素。
- 任务队列:用于缓存提交的任务。
- 线程数量管理功能:一个线程池必须能够很好地管理和控制线程数量,可通过如下三个参数来实现,比如创建线程池时初始的线程数量init;线程池自动扩充时最大的线程数量max;在线程池空闲时需要释放线程但是也要维护一定数量的活跃数量或者核心数量c。re。有了这三个参数,就能够很好地控制线程池中的线程数量,将其维护在一个合理的范围之内,三者之间的关系是init<=core«=maxo
- 任务拒绝策略:如果线程数量已达到上限且任务队列已满,则需要有相应的拒绝策略来通知任务提交者。
- 线程工厂:主要用于个性化定制线程,比如将线程设置为守护线程以及设置线程名称等。
- QueueSize:任务队列主要存放提交的Ru皿able,但是为了防止内存溢出,需要有limit数量对其进行控制。
- Keepedalive时间:该时间主要决定线程各个重要参数自动维护的时间间隔。
二、线程池实现例子
- ThreadPool.java接口,线程池基本操作
package p126_thread_pool;
public interface ThreadPool {
void execute(Runnable runnable);
void shutdown();
int getInitSize();
int getCoreSize();
int getMaxSize();
int getQueueSize();
int getActiveCount();
boolean isShutdown();
}
- ThreadFactory.java接口,创建个性化线程
package p126_thread_pool;
@FunctionalInterface
public interface ThreadFactory {
Thread createThread(Runnable runnable);
}
- RunnableQueue.java接口,线程队列基本操作
package p126_thread_pool;
public interface RunnableQueue {
void offer(Runnable runnable);
Runnable take() throws InterruptedException;
int size();
}
- DenyPolicy.java接口,线程池满时拒绝策略
package p126_thread_pool;
@FunctionalInterface
public interface DenyPolicy {
void reject(Runnable runnable,ThreadPool threadPool);
class DiscardDenyPolicy implements DenyPolicy{
@Override
public void reject(Runnable runnable, ThreadPool threadPool) {
}
}
class AbortDenyPolicy implements DenyPolicy{
@Override
public void reject(Runnable runnable, ThreadPool threadPool) {
throw new RunnableDenyException("The runnable "+runnable+" vill" +
" be abort.");
}
}
class RunnableDenyPolicy implements DenyPolicy{
@Override
public void reject(Runnable runnable, ThreadPool threadPool) {
if (!threadPool.isShutdown()){
runnable.run();
}
}
}
}
- InternalTask.java不断从runnableQueue中取出Runnable并执行任务
package p126_thread_pool;
public class InternalTask implements Runnable {
private final RunnableQueue runnableQueue;
private volatile boolean running = true;
public InternalTask(RunnableQueue runnableQueue) {
this.runnableQueue = runnableQueue;
}
@Override
public void run() {
while (running && !Thread.currentThread().isInterrupted()){
try {
Runnable task = runnableQueue.take();
task.run();
}catch (InterruptedException e){
running = false;
break;
}
}
}
public void stop(){
this.running = false;
}
}
- LinkedRunnableQueue.java双向循环链表实现线程任务队列RunnableQueue基本操作
package p126_thread_pool;
import java.util.LinkedList;
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.addLast(runnable);
runnableList.notifyAll();
}
}
}
@Override
public Runnable take() throws InterruptedException {
synchronized (runnableList){
while (runnableList.isEmpty()){
try {
runnableList.wait();
}catch (InterruptedException e){
throw e;
}
}
return runnableList.removeFirst();
}
}
@Override
public int size() {
synchronized (runnableList){
return runnableList.size();
}
}
}
- RunnableDenyException.java错误抛出
package p126_thread_pool;
public class RunnableDenyException extends RuntimeException {
public RunnableDenyException(String message){
super(message);
}
}
- BasicThreadPool.java实现ThreadPool
package p126_thread_pool;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class BasicThreadPool extends Thread implements ThreadPool {
private final int initSize;
private final int maxSize;
private final int coreSize;
private int activeCount;
private final ThreadFactory threadFactory;
private final RunnableQueue runnableQueue;
private volatile boolean isShutdown = false;
private final Queue<ThreadTask> threadQueue = new ArrayDeque<>();
private static final DenyPolicy DEFAULT_DENY_POLICY = new DenyPolicy.DiscardDenyPolicy();
private static final ThreadFactory DEFAULT_THREAD_FACTORY = new DefaultThreadFactory();
private final long keepAliveTime;
private final TimeUnit timeUnit;
public BasicThreadPool(int initSize,int maxSize,int coreSize,int queueSize){
this(initSize,maxSize,coreSize,DEFAULT_THREAD_FACTORY,queueSize,
DEFAULT_DENY_POLICY,10,TimeUnit.SECONDS);
}
public BasicThreadPool(int initSize, int maxSize, int coreSize, ThreadFactory threadFactory,
int queueSize,DenyPolicy denyPolicy,
long keepAliveTime, TimeUnit timeUnit) {
this.initSize = initSize;
this.maxSize = maxSize;
this.coreSize = coreSize;
this.threadFactory = threadFactory;
this.runnableQueue = new LinkedRunnableQueue(queueSize,denyPolicy,this);
this.keepAliveTime = keepAliveTime;
this.timeUnit = timeUnit;
this.init();
}
private void init(){
start();
for (int i = 0; i < initSize; i++){
newThread();
}
}
@Override
public void execute(Runnable runnable) {
if (this.isShutdown){
throw new IllegalStateException("The thread pool is destroy");
}
this.runnableQueue.offer(runnable);
}
private void newThread(){
InternalTask internalTask=new InternalTask(runnableQueue);
Thread thread=this.threadFactory.createThread(internalTask);
ThreadTask threadTask=new ThreadTask(thread,internalTask);
threadQueue.offer(threadTask);
this.activeCount++;
thread.start();
}
private void removeThread(){
ThreadTask threadTask=threadQueue.remove();
threadTask.internalTask.stop();
this.activeCount--;
}
@Override
public void run() {
while (!isShutdown && !isInterrupted()){
try {
timeUnit.sleep(keepAliveTime);
}catch (InterruptedException e){
isShutdown=true;
break;
}
synchronized (this){
if (isShutdown){
break;
}
if (runnableQueue.size()>0&&activeCount<coreSize){
for (int i=initSize;i<coreSize;i++){
newThread();
}
continue;
}
if (runnableQueue.size()>0&&activeCount<maxSize){
for (int i=coreSize;i<maxSize;i++){
newThread();
}
}
if (runnableQueue.size()==0&&activeCount>coreSize){
for (int i=coreSize;i<activeCount;i++){
removeThread();
}
}
}
}
}
@Override
public void shutdown() {
synchronized (this){
if (isShutdown)return;
isShutdown=true;
threadQueue.forEach(threadTask -> {
threadTask.internalTask.stop();
threadTask.thread.interrupt();
});
this.interrupt();
}
}
@Override
public int getInitSize() {
if (isShutdown)
throw new IllegalStateException("The thread pool is destroy");
return this.initSize;
}
@Override
public int getCoreSize() {
if (isShutdown)
throw new IllegalStateException("The thread pool is destroy");
return this.coreSize;
}
@Override
public int getQueueSize() {
if (isShutdown)
throw new IllegalStateException("The thread pool is destroy");
return runnableQueue.size();
}
@Override
public int getMaxSize() {
if (isShutdown)
throw new IllegalStateException("The thread pool is destroy");
return this.maxSize;
}
@Override
public int getActiveCount() {
if (isShutdown)
throw new IllegalStateException("The thread pool is destroy");
return this.activeCount;
}
@Override
public boolean isShutdown() {
return this.isShutdown;
}
private static class ThreadTask{
Thread thread;
InternalTask internalTask;
public ThreadTask(Thread thread, InternalTask internalTask) {
this.thread = thread;
this.internalTask = internalTask;
}
}
private static class DefaultThreadFactory implements ThreadFactory{
private static final AtomicInteger group_counter=new AtomicInteger(1);
private static final ThreadGroup group =
new ThreadGroup("myGroup-"+group_counter.getAndDecrement());
public static final AtomicInteger COUNTER =new AtomicInteger(0);
@Override
public Thread createThread(Runnable runnable) {
return new Thread(group,runnable,"thread-poll-"+COUNTER.getAndDecrement());
}
}
}
- ThreadPoolTest.java测试线程池
package p126_thread_pool;
import java.util.concurrent.TimeUnit;
public class ThreadPoolTest {
public static void main(String[] args) throws InterruptedException {
final ThreadPool threadPool=new BasicThreadPool(2,6,4,1000);
for (int i=0;i<20;i++){
threadPool.execute(()->{
try {
TimeUnit.SECONDS.sleep(10);
System.out.println(Thread.currentThread().getName()+" is" +
" running and done.");
}catch (InterruptedException e){
e.printStackTrace();
}
});
}
for (; ; ){
System.out.println("getActiveCount = "+threadPool.getActiveCount());
System.out.println("getQueueSize = "+threadPool.getQueueSize());
System.out.println("getCoreSize = "+threadPool.getCoreSize());
System.out.println("getMaxSize = "+threadPool.getMaxSize());
System.out.println("==========================================");
TimeUnit.SECONDS.sleep(5);
}
}
}
- 运行结果
