关于队列概念
详见:JAVA 多线程中的队列分类:阻塞队列,有界队列,无界队列
常用队列
ArrayBlockingQueue: 有界队列,基于数组结构,按照队列FIFO原则对元素排序;LinkedBlockingQueue:无界、无界队列,基于链表结构,按照队列FIFO原则对元素排序,效率高,推荐Executors.newFixedThreadPool()使用了这个队列SynchronousQueue:同步队列, 该队列不存储元素,每个插入操作必须等待另一个线程调用移除操作,否则插入操作会一直被阻塞,Executors.newCachedThreadPool()使用了这个队列;PriorityBlockingQueue:支持优先级排序的无界阻塞队列。DelayQueue: 一个使用优先级队列实现的无界阻塞队列LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列
ArrayBlockingQueue
基于数组实现的有界阻塞队列,ArrayBlockingQueue 内部维护这一个定长数组,阻塞队列的大小在初始化时就已经确定了,其后无法更改。
ArrayBlockingQueue 支持公平性和非公平性,默认采用非公平模式,可以通过构造函数设置为公平访问策略。
LinkedBlockingDeque
LinkedBlockingDeque是一个有链表组成的双向阻塞队列,与前面的阻塞队列相比它支持从两端插入和移出元素。以first结尾的表示从对头操作,以last结尾的表示从对尾操作。
在初始化LinkedBlockingDeque时可以初始化队列的容量,用来防止其再扩容时过渡膨胀。另外双向阻塞队列可以运用在“工作窃取”模式中。
ArrayBlockingQueue VS LinkedBlockingDeque
ArrayBlockingQueue
数据结构:数组,存储空间预先分配,无需动态申请空间,使用过程中内存开销较小;
LinkedBlockingQueue:
数据结构:单项链表,存储空间动态申请,会增加JVM垃圾回收负担;
两把锁,并发性能较好;
可设置为无界,吞吐量比较大,但是不稳定,入队速度太快有可能导致内存溢出。
PriorityBlockingQueue
PriorityBlockingQueue 是支持优先级的无界队列。默认情况下采用自然顺序排序,当然也可以通过自定义Comparator来指定元素的排序顺序,不能保证同优先级元素的顺序。
PriorityBlockingQueue 内部采用二叉堆的实现方式。
SynchronousQueue
SynchronousQueue 是一个神奇的队列,他是一个不存储元素的阻塞队列,也就是说他的每一个put操作都需要等待一个take操作,否则就不能继续添加元素了,有点儿像Exchanger,类似于生产者和消费者进行交换。
队列本身不存储任何元素,所以非常适用于传递性场景,两者直接进行对接。其吞吐量会高于ArrayBlockingQueue和LinkedBlockingQueue。
SynchronousQueue支持公平和非公平的访问策略,在默认情况下采用非公平性,也可以通过构造函数来设置为公平性。
SynchronousQueue的实现核心为Transferer接口,该接口有TransferQueue和TransferStack两个实现类,分别对应着公平策略和非公平策略。接口Transferer有一个tranfer()方法,该方法定义了转移数据,如果e != null,相当于将一个数据交给消费者,如果e == null,则相当于从一个生产者接收一个消费者交出的数据。
例子
本例中,corePoolSize、maximumPoolSize 都是1,workQueue 的大小是2,即:只有1个线程在运行,最多有2个线程放入队列中等待
package ThreadPool;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Instance2 {
public static void main(String[] args) {
LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue(2);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
1,
1,
10,
TimeUnit.SECONDS,
linkedBlockingQueue
);
print(threadPoolExecutor);
threadPoolExecutor.execute(new MyRun("1",threadPoolExecutor));
threadPoolExecutor.execute(new MyRun("2",threadPoolExecutor));
threadPoolExecutor.execute(new MyRun("3",threadPoolExecutor));
// 关闭线程池
threadPoolExecutor.shutdown();
}
static void print(ThreadPoolExecutor threadPoolExecutor){
System.out.println("活动线程数:"+threadPoolExecutor.getActiveCount());
System.out.println("线程池中的线程数:"+threadPoolExecutor.getPoolSize());
System.out.println("队列中的线程数:"+threadPoolExecutor.getQueue().size());
System.out.println("完成的线程数:"+threadPoolExecutor.getCompletedTaskCount());
}
static class MyRun implements Runnable {
String name;
ThreadPoolExecutor threadPoolExecutor;
public MyRun(String name, ThreadPoolExecutor threadPoolExecutor) {
this.name = name;
this.threadPoolExecutor = threadPoolExecutor;
}
@Override
public void run() {
System.out.println("----"+name+" 线程开始");
print(threadPoolExecutor);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("===="+name+" 线程结束");
}
}
}
如果提交第4个线程就报错
package ThreadPool;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Instance2_超过队列大小报错 {
public static void main(String[] args) {
LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue(2);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
1,
1,
10,
TimeUnit.SECONDS,
linkedBlockingQueue
);
print(threadPoolExecutor);
threadPoolExecutor.execute(new MyRun("1",threadPoolExecutor));
threadPoolExecutor.execute(new MyRun("2",threadPoolExecutor));
threadPoolExecutor.execute(new MyRun("3",threadPoolExecutor));
try {
threadPoolExecutor.execute(new MyRun("4", threadPoolExecutor));
}catch (Exception e){
System.out.println("超过队列大小,抛出异常:"+e);
}
// 关闭线程池
threadPoolExecutor.shutdown();
}
static void print(ThreadPoolExecutor threadPoolExecutor){
System.out.println("活动线程数:"+threadPoolExecutor.getActiveCount());
System.out.println("线程池中的线程数:"+threadPoolExecutor.getPoolSize());
System.out.println("队列中的线程数:"+threadPoolExecutor.getQueue().size());
System.out.println("完成的线程数:"+threadPoolExecutor.getCompletedTaskCount());
}
static class MyRun implements Runnable {
String name;
ThreadPoolExecutor threadPoolExecutor;
public MyRun(String name, ThreadPoolExecutor threadPoolExecutor) {
this.name = name;
this.threadPoolExecutor = threadPoolExecutor;
}
@Override
public void run() {
System.out.println("----"+name+" 线程开始");
print(threadPoolExecutor);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("===="+name+" 线程结束");
}
}
}
报错如下:
例子2
corePoolSize 是1,maximumPoolSize 是2,队列大小是1
提交
线程1时,线程1开始运行,此时线程池中有1个活动线程提交
线程2时,由于corePoolSize 是1,此时线程池中有1个活动线程,会将线程2放到队列中,此时队列满(队列大小为1)提交
线程3时,由于队列已满,但maximumPoolSize是2,就继续创建1个线程,并运行
代码:
package ThreadPool;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Instance3 {
public static void main(String[] args) {
LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue(1);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
1,
2,
10,
TimeUnit.SECONDS,
linkedBlockingQueue
);
print("主线程",threadPoolExecutor);
threadPoolExecutor.execute(new MyRun("1",threadPoolExecutor));
threadPoolExecutor.execute(new MyRun("2",threadPoolExecutor));
threadPoolExecutor.execute(new MyRun("3",threadPoolExecutor));
// 关闭线程池
threadPoolExecutor.shutdown();
}
static void print(String name,ThreadPoolExecutor threadPoolExecutor){
System.out.println(name+" 活动线程数:"+threadPoolExecutor.getActiveCount());
System.out.println(name+" 线程池中的线程数:"+threadPoolExecutor.getPoolSize());
System.out.println(name+" 队列中的线程数:"+threadPoolExecutor.getQueue().size());
System.out.println(name+" 完成的线程数:"+threadPoolExecutor.getCompletedTaskCount());
}
static class MyRun implements Runnable {
String name;
ThreadPoolExecutor threadPoolExecutor;
public MyRun(String name, ThreadPoolExecutor threadPoolExecutor) {
this.name = name;
this.threadPoolExecutor = threadPoolExecutor;
}
@Override
public void run() {
System.out.println("----"+name+" 线程开始");
print("线程-"+name,threadPoolExecutor);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("===="+name+" 线程结束");
}
}
}
参考:
https://www.jianshu.com/p/b1d383d4021c
参考:
https://blog.csdn.net/u022812849/article/details/114698692

