java线程池
目前只写到能正确创建线程,线程扩容到最大线程数,还没写线程池缩容和shutdown。
能正确运用线程池创建线程并执行任务。
测试和结果
当前测试使用线程池无参构造函数(无参构造器其实本质上调用了 7 参数构造器, 7 参数构造器和 JDK 源码的构造器一样),corePoolSize = 5, maximumPoolSize = 8, 阻塞队列最大容量是16。(如果任务数超过 corePoolSize 且没到阻塞队列容量的 1/4 ,把任务放入阻塞队列等待,否则继续新建线程数直到到达 maximumPoolSize。
22:30:41.336 [main] INFO java.util.concurrent.ThreadFactory - workers number < corePoolsize, create a new worker worker num : 0
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - workers number < corePoolsize, create a new worker worker num : 1
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - workers number < corePoolsize, create a new worker worker num : 2
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.343 [main] INFO java.util.concurrent.ThreadFactory - workers number < corePoolsize, create a new worker worker num : 3
22:30:41.344 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.344 [main] INFO java.util.concurrent.ThreadFactory - workers number < corePoolsize, create a new worker worker num : 4
22:30:41.344 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.344 [main] INFO java.util.concurrent.ThreadFactory - workers number < maximumPoolSize, put in to queue until enough tasks awaiting worker num : 5
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - workers number < maximumPoolSize, put in to queue until enough tasks awaiting worker num : 5
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - workers number < maximumPoolSize, put in to queue until enough tasks awaiting worker num : 5
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - workers number < maximumPoolSize, put in to queue until enough tasks awaiting worker num : 5
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - workers number < maximumPoolSize, put in to queue until enough tasks awaiting worker num : 5
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - poolSize > awaiting workers number, create new Thread worker num : 6
22:30:41.345 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.346 [main] INFO java.util.concurrent.ThreadFactory - poolSize > awaiting workers number, create new Thread worker num : 7
22:30:41.346 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.346 [main] INFO java.util.concurrent.ThreadFactory - poolSize > awaiting workers number, create new Thread worker num : 8
22:30:41.346 [main] INFO java.util.concurrent.ThreadFactory - get worker and starting...
22:30:41.346 [main] INFO java.util.concurrent.ThreadFactory - no available workers, put tasks into queue worker num : 8
22:30:41.347 [main] INFO java.util.concurrent.ThreadFactory - no available workers, put tasks into queue worker num : 8
java 代码
package com.xxx.springboot.myThreadPool;
import org.apache.camel.model.GlobalOptionDefinition;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadPool {
private static final Logger logger = LoggerFactory.getLogger(ThreadFactory.class);
private final AtomicInteger workCount = new AtomicInteger(0);
private final AtomicInteger taskCount = new AtomicInteger(0);
private final BlockingQueue<Runnable> workQueue;
private final ThreadFactory threadFactory;
private final int corePoolSize;
private final int maximumPoolSize;
private final long keepAliveTime;
private final RejectedExecutionHandler handler;
private final HashSet<Worker> workers = new HashSet<>();
private final int awaitingWorkerNumber;
/**
* 锁住 能操作 workers
*/
private final ReentrantLock mainLock = new ReentrantLock();
private final Condition termination = mainLock.newCondition();
private int largestPoolSize;
private long completedTaskCount;
/**
*
*/
public ThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory, RejectedExecutionHandler handler) {
//logger.info("constructing the ThreadPool class...");
if (corePoolSize < 0 || maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize || keepAliveTime < 0) {
logger.error("wrong arguments detected...");
throw new IllegalArgumentException();
}
if (workQueue == null || threadFactory == null || handler == null) {
logger.error("null argument...");
throw new NullPointerException();
}
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.awaitingWorkerNumber = workQueue.remainingCapacity() / 4;
this.handler = handler;
//logger.info("finish constructing the ThreadPool class...");
}
/**
* default constructor
*/
public ThreadPool() {
this(5, 8, 2000, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(16), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
//logger.info("using non-args constructor...");
}
public void execute(Runnable command) {
if (command == null) {
logger.error("runnable task is null...");
throw new NullPointerException();
}
try {
mainLock.lock();
Worker worker = acquireWorker(command);
if (worker != null) {
logger.info("get worker and starting...");
worker.execute();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
mainLock.unlock();
}
}
private Worker acquireWorker(Runnable command) {
mainLock.lock();
try {
if (workCount.get() < corePoolSize) {
logger.info("workers number < corePoolsize, create a new worker" + " worker num : " + workCount.get());
Worker worker = createWorker(command);
taskCount.set(taskCount.get() + 1);
return worker;
} else if (workCount.get() < maximumPoolSize) {
/**
* if awaiting tasks > 1 / 4 Queue.size ,create new worker
*/
if (taskCount.get() - workCount.get() <= awaitingWorkerNumber) {
workQueue.add(command);
taskCount.set(taskCount.get() + 1);
logger.info("workers number < maximumPoolSize, put in to queue until enough tasks awaiting" + " worker num : " + workCount.get());
} else {
Worker worker = createWorker(workQueue.take());
workQueue.add(command);
taskCount.set(taskCount.get() + 1);
logger.info("poolSize > awaiting workers number, create new Thread" + " worker num : " + workCount.get());
return worker;
}
} else {
try {
workQueue.add(command);
taskCount.set(taskCount.get() + 1);
logger.info("no available workers, put tasks into queue" + " worker num : " + workCount.get());
} catch (IllegalStateException e) {
e.printStackTrace();
logger.warn("workQueue is full, discarding the work..." + " worker num : " + workCount.get());
}
}
} catch (Exception e) {
e.printStackTrace();
logger.info("error encountered while acquiring worker" + " worker num : " + workCount.get());
} finally {
mainLock.unlock();
}
return null;
}
/**
* only accessed by acquireWorker() function
* @param command
* @return
*/
private Worker createWorker(Runnable command) {
workCount.set(workCount.get() + 1);
Worker worker = new Worker(command);
workers.add(worker);
return worker;
}
/**
* AQS
*/
private final class Worker extends AbstractQueuedSynchronizer implements Runnable {
final Thread thread;
Runnable firstTask;
/**
* 先前执行任务计数器
*/
volatile long completedTasks;
Worker(Runnable firstTask) {
//logger.info("Initializing Workers's constructor... ");
setState(-1);
this.firstTask = firstTask;
this.thread = threadFactory.newThread(firstTask);
}
@Override
public void run() {
}
public void execute() {
//logger.info("Workers is running using " + Thread.currentThread().getName());
thread.start();
}
}
public String getCurrentTime() {
StringBuilder res = new StringBuilder();
long time = new Date().getTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
String format = sdf.format(time);
res.append(format);
res.append(" ");
return res.toString();
}
}