java多線程:線程池常用的三種隊列詳解!

開篇:我們在初始化線程池的時候常常會使用到如下三種隊列,他們分別是:

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
---------------------

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章