開篇:我們在初始化線程池的時候常常會使用到如下三種隊列,他們分別是:
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
---------------------