Java内置线程池
线程池有几个核心参数:1、核心线程数 2、最大线程数 3、阻塞队列
1、线程池创建时,不会创建线程。
2、当有任务到来时,如果当前执行线程数少于核心线程数,会创建线程执行,不管是否有其它线程正在执行。
3、如果当前执行线程数等于核心线程数,新来的线程会进入阻塞队列。
4、如果阻塞队列已经满了,而且当前线程数小于核心线程数,会开启新线程先执行执行新到来的任务,当其它线程执行完毕时会从阻塞队列中取出任务执行。
5、如果当前正在执行的线程等于最大线程数,且阻塞队列已满则会执行拒绝策略。
对于第二点,测试代码如下:
public class ThreadPoolTest implements Runnable {
private int number;
public ThreadPoolTest(int number){
this.number = number;
}
public void run() {
try {
System.out.println("线程"+Thread.currentThread().getName()+"执行完毕="+number);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 1000, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1));
// 当前执行线程数0
System.out.println("当前执行线程数:"+executor.getActiveCount());
int i = 0;
executor.submit(new ThreadPoolTest(i));
// 等待第一个线程执行完毕
Thread.sleep(1000);
i++;
executor.submit(new ThreadPoolTest(i));
Thread.sleep(100000);
executor.shutdown();
}
}
对于第三点,测试代码如下:
public class ThreadPoolTest implements Runnable {
private int number;
public ThreadPoolTest(int number){
this.number = number;
}
public void run() {
try {
Thread.sleep(2000);
System.out.println("线程"+Thread.currentThread().getName()+"执行完毕="+number);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 1000, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1));
// 当前执行线程数0
System.out.println("当前执行线程数:"+executor.getActiveCount());
int i = 0;
for (; i < 3; i++) {
executor.submit(new ThreadPoolTest(i));
}
Thread.sleep(100000);
executor.shutdown();
}
}
对于第四点,测试代码如下:
public class ThreadPoolTest implements Runnable {
private int number;
public ThreadPoolTest(int number){
this.number = number;
}
public void run() {
try {
Thread.sleep(5500);
System.out.println("线程"+Thread.currentThread().getName()+"执行完毕="+number);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 1000, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1));
// 当前执行线程数0
System.out.println("当前执行线程数:"+executor.getActiveCount());
int i = 0;
for (; i < 4; i++) {
executor.submit(new ThreadPoolTest(i));
}
}
}
对于第五点,测试代码如下:
public class ThreadPoolTest implements Runnable {
private int number;
public ThreadPoolTest(int number){
this.number = number;
}
public void run() {
try {
Thread.sleep(2000);
System.out.println("线程"+Thread.currentThread().getName()+"执行完毕="+number);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 1000, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1));
// 当前执行线程数0
System.out.println("当前执行线程数:"+executor.getActiveCount());
int i = 0;
for (; i < 6; i++) {
executor.submit(new ThreadPoolTest(i));
}
Thread.sleep(100000);
executor.shutdown();
}
}
Tomcat线程池
Tomcat线程池类是:org.apache.tomcat.util.threads.ThreadPoolExecutor
跑上面的测试代码,会发现和Java的线程池存在不同,主要体现在第3,4,5点上关于阻塞队列。
Tomcat的线程池在当前执行线程数量不超过最大线程数量时,会直接开启新线程执行,只有当线程数等于最大线程数量时,才会将请求进行排队,等到队列满了的时候,会执行拒绝策略。
对于Java内置线程的改动主要体现在TaskQueue队列上,默认的Java线程池在核心线程满了之后会将任务放在阻塞队列上,Tomcat线程池继承拓展了Java线程池,并提供了TaskQueue的阻塞队列实现,重写了队列的offer方法,在判断当前线程数小于最大线程数时,offer方法会返回false,导致默认的Java线程池去创建新的线程执行任务。
代码如下:
// java.util.concurrent.ThreadPoolExecutor
public void execute(Runnable command) {
// 省略部分代码
// 主要看下面的if中workQueue.offer(command),当前线程数小于最大线程数时,这里返回了false
if (isRunning(c) && workQueue.offer(command)) {
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);
}
// org.apache.tomcat.util.threads.TaskQueue
public boolean offer(Runnable o) {
// 省略部分代码
// 主要是这里,这里的parent是线程池对象,创建队列时tomcat注入了线程池对象
//if we have less threads than maximum force creation of a new thread
if (parent.getPoolSize()<parent.getMaximumPoolSize()) {
return false;
}
//if we reached here, we need to add it to the queue
return super.offer(o);
}
标签:int,number,线程,executor,new,public
From: https://www.cnblogs.com/zanpocc/p/16724794.html