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

 

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