开篇:我们在初始化线程池的时候常常会使用到如下三种队列,他们分别是:
LinkedBlockingDeque(链表同步阻塞队列)、ArrayBlockingQueue(数组同步阻塞队列)、SynchronousQueue(同步阻塞队列)
他们与线程池的的maximumPoolSize参数结合使用时会有不同的效果。
通过实验来说明:
1.使用ArrayBlockingQueue
(1).源码
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
(2).代码实例
a.当Runnable的数量小于等于maximumPoolSize与阻塞队列的和
package com.springboot.thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadQueueTest {
public static void main(String[] args) {
ArrayBlockingQueue linked = new ArrayBlockingQueue(2);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,1L, TimeUnit.SECONDS,linked);
ThreadQueueRunnable runnable = new ThreadQueueRunnable();
System.out.println("before thread pool execute linked size is :"+linked.size());
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
System.out.println("after thread pool execute linked size is :"+linked.size());
System.out.println("thread pool size is:" + threadPoolExecutor.getPoolSize());
}
}
class ThreadQueueRunnable implements Runnable{
@Override
public void run() {
System.out.println("--------------------");
System.out.println(Thread.currentThread().getName());
System.out.println("---------------------");
}
}
运行结果:
before thread pool execute linked size is :0
--------------------
pool-1-thread-1
---------------------
--------------------
pool-1-thread-3
---------------------
--------------------
pool-1-thread-3
---------------------
after thread pool execute linked size is :2
thread pool size is:3
--------------------
pool-1-thread-2
---------------------
--------------------
pool-1-thread-1
---------------------
b.当Runnable的数量大于maximumPoolSize与阻塞队列的和
package com.springboot.thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadQueueTest {
public static void main(String[] args) {
ArrayBlockingQueue linked = new ArrayBlockingQueue(2);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,1L, TimeUnit.SECONDS,linked);
ThreadQueueRunnable runnable = new ThreadQueueRunnable();
System.out.println("before thread pool execute linked size is :"+linked.size());
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
System.out.println("after thread pool execute linked size is :"+linked.size());
System.out.println("thread pool size is:" + threadPoolExecutor.getPoolSize());
}
}
class ThreadQueueRunnable implements Runnable{
@Override
public void run() {
System.out.println("--------------------");
System.out.println(Thread.currentThread().getName());
System.out.println("---------------------");
}
}
运行结果:
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.springboot.thread.ThreadQueueRunnable@58372a00 rejected from java.util.concurrent.ThreadPoolExecutor@4dd8dc3[Running, pool size = 3, active threads = 3, queued tasks = 2, completed tasks = 0]
before thread pool execute linked size is :0
--------------------
pool-1-thread-1
---------------------
--------------------
pool-1-thread-1
---------------------
--------------------
pool-1-thread-1
---------------------
--------------------
pool-1-thread-2
---------------------
--------------------
pool-1-thread-3
---------------------
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
at com.springboot.thread.ThreadQueueTest.main(ThreadQueueTest.java:18)
总结一下:当我们使用ArrayBlockingQueue时,当runnable的数量小于等于线程池的大小与队列的和时,会先将部分runnable存到线程池中立刻开始执行,将剩余的runnable存入阻塞队列中。当runnable的数量大于线程池的数量与阻塞队列之和时会将线程池+阻塞队列数量的runnable执行,并抛出RejectedExecutionException,使用LinkedBlockingDeque时同理。
(LinkedBlockingQueue和LinkedBlockingDeque分析:参考 https://blog.csdn.net/anLA_/article/details/79027867)
2.使用SynchronousQueue
a.当Runnable的数量小于等于maximumPoolSize
package com.springboot.thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadQueueTest {
public static void main(String[] args) {
//ArrayBlockingQueue linked = new ArrayBlockingQueue(2);
SynchronousQueue linked = new SynchronousQueue();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,1L, TimeUnit.SECONDS,linked);
ThreadQueueRunnable runnable = new ThreadQueueRunnable();
System.out.println("before thread pool execute linked size is :"+linked.size());
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
//threadPoolExecutor.execute(runnable);
System.out.println("after thread pool execute linked size is :"+linked.size());
System.out.println("thread pool size is:" + threadPoolExecutor.getPoolSize());
}
}
class ThreadQueueRunnable implements Runnable{
@Override
public void run() {
System.out.println("--------------------");
System.out.println(Thread.currentThread().getName());
System.out.println("---------------------");
}
}
运行结果:
before thread pool execute linked size is :0
after thread pool execute linked size is :0
thread pool size is:3
--------------------
pool-1-thread-1
---------------------
--------------------
pool-1-thread-3
---------------------
--------------------
pool-1-thread-2
---------------------
b.当Runnable的数量大于maximumPoolSize
package com.springboot.thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadQueueTest {
public static void main(String[] args) {
//ArrayBlockingQueue linked = new ArrayBlockingQueue(2);
SynchronousQueue linked = new SynchronousQueue();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,1L, TimeUnit.SECONDS,linked);
ThreadQueueRunnable runnable = new ThreadQueueRunnable();
System.out.println("before thread pool execute linked size is :"+linked.size());
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
System.out.println("after thread pool execute linked size is :"+linked.size());
System.out.println("thread pool size is:" + threadPoolExecutor.getPoolSize());
}
}
class ThreadQueueRunnable implements Runnable{
@Override
public void run() {
System.out.println("--------------------");
System.out.println(Thread.currentThread().getName());
System.out.println("---------------------");
}
}
运行结果:
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.springboot.thread.ThreadQueueRunnable@4dd8dc3 rejected from java.util.concurrent.ThreadPoolExecutor@6d03e736[Running, pool size = 3, active threads = 3, queued tasks = 0, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
at com.springboot.thread.ThreadQueueTest.main(ThreadQueueTest.java:18)
before thread pool execute linked size is :0
--------------------
pool-1-thread-1
---------------------
--------------------
pool-1-thread-3
---------------------
--------------------
pool-1-thread-2
---------------------
总结一下:当我们使用同步阻塞队列时,同步阻塞队列没有大小,当runnable的数量小于等于线程池的大小时每执行一次 threadPoolExecutor.execute(runnable);线程池的大小会加1,当超过线程池的的大时不再执行多余的任务并抛出RejectedExecutionException异常。
补代码:
package com.springboot.thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadQueueTest {
public static void main(String[] args) {
//ArrayBlockingQueue linked = new ArrayBlockingQueue(2);
SynchronousQueue linked = new SynchronousQueue();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,1L, TimeUnit.SECONDS,linked);
ThreadQueueRunnable runnable = new ThreadQueueRunnable();
System.out.println("before thread pool execute linked size is :"+linked.size());
System.out.println("thread pool size is:" + threadPoolExecutor.getPoolSize());
threadPoolExecutor.execute(runnable);
threadPoolExecutor.execute(runnable);
//threadPoolExecutor.execute(runnable);
System.out.println("thread pool size is:" + threadPoolExecutor.getPoolSize());
threadPoolExecutor.execute(runnable);
System.out.println("after thread pool execute linked size is :"+linked.size());
System.out.println("thread pool size is:" + threadPoolExecutor.getPoolSize());
}
}
class ThreadQueueRunnable implements Runnable{
@Override
public void run() {
System.out.println("--------------------");
System.out.println(Thread.currentThread().getName());
System.out.println("---------------------");
}
}
运行结果:
before thread pool execute linked size is :0
thread pool size is:0
thread pool size is:2
after thread pool execute linked size is :0
--------------------
pool-1-thread-2
---------------------
thread pool size is:3
--------------------
pool-1-thread-3
---------------------
--------------------
pool-1-thread-1
---------------------