目录
在使用ThreadPoolExecutor线程池的时候,需要指定一个实现了BlockingQueue接口的任务等待队列,用于临时存储提交的任务。
有限队列
SynchronousQueue
SynchronousQueue 是一个不存储元素的阻塞队列。它每个插入操作必须等待另一个线程调用移除操作,否则插入操作将一直处于阻塞状态
在 ThreadPoolExecutor
中使用 SynchronousQueue
作为任务队列时,会有以下特点:
- 无存储:由于
SynchronousQueue
不存储任务,因此它非常适合于需要立即执行任务的场景。每个提交给线程池的任务都必须立即由一个空闲的线程来执行,否则提交操作将会阻塞。 - 高吞吐量:在没有任务积压的情况下,
SynchronousQueue
可以提供非常高的吞吐量,因为任务是直接传递给执行它们的线程的。 - 必须配置足够的线程:由于队列不存储任务,如果提交任务的速度超过了线程池处理任务的速度,并且没有足够的线程来立即执行这些任务,那么提交操作将会阻塞。因此,需要确保线程池有足够的线程来处理提交的任务。
- 任务拒绝策略:如果线程池已经达到了它的最大线程数,并且所有的线程都在忙碌中,那么新提交的任务将会被拒绝。需要为线程池配置一个合适的任务拒绝策略来处理这种情况
SynchronousQueue 队列构造函数
/**
* Creates a {@code SynchronousQueue} with nonfair access policy.
*/
public SynchronousQueue() {
this(false);
}
/**
* Creates a {@code SynchronousQueue} with the specified fairness policy.
*
* @param fair if true, waiting threads contend in FIFO order for
* access; otherwise the order is unspecified.
*/
public SynchronousQueue(boolean fair) {
transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
}
SynchronousQueue 队列使用示例
import java.util.concurrent.*;
public class ThreadPoolExecutorExample {
public static void main(String[] args) {
// 创建一个 SynchronousQueue 实例
SynchronousQueue<Runnable> synchronousQueue = new SynchronousQueue<>();
// 创建一个 ThreadPoolExecutor 实例,使用 SynchronousQueue 作为任务队列
ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, // 核心线程数
4, // 最大线程数
0L, // 线程空闲时间
TimeUnit.MILLISECONDS,
synchronousQueue, // 任务队列
new ThreadPoolExecutor.AbortPolicy() // 任务拒绝策略:直接抛出异常
);
// 提交任务给线程池执行
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " is executing task.");
});
}
}
}
ArrayBlockingQueue
ArrayBlockingQueue 是一个可选有界队列,默认情况下是无界的(但可以在构造函数中指定容量)。该队列按照先进先出(FIFO)的原则对元素进行排序,新的任务加入到队列尾部,队列获取操作是从队列头部获取任务。
这个队列有固定大小,一旦创建了这样的缓存区,就不能再增加容量。试图向已经满的队列增加任务,会导致操作受到阻塞。同样的,试图从空的队列中获取任务也会受到阻塞。
ArrayBlockingQueue 队列构造函数
/**
* Creates a {@code LinkedBlockingQueue} with a capacity of
* {@link Integer#MAX_VALUE}.
*/
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
/**
* Creates a {@code LinkedBlockingQueue} with the given (fixed) capacity.
*
* @param capacity the capacity of this queue
* @throws IllegalArgumentException if {@code capacity} is not greater
* than zero
*/
public LinkedBlockingQueue(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
last = head = new Node<E>(null);
}
/**
* Creates a {@code LinkedBlockingQueue} with a capacity of
* {@link Integer#MAX_VALUE}, initially containing the elements of the
* given collection,
* added in traversal order of the collection's iterator.
*
* @param c the collection of elements to initially contain
* @throws NullPointerException if the specified collection or any
* of its elements are null
*/
public LinkedBlockingQueue(Collection<? extends E> c) {
this(Integer.MAX_VALUE);
final ReentrantLock putLock = this.putLock;
putLock.lock(); // Never contended, but necessary for visibility
try {
int n = 0;
for (E e : c) {
if (e == null)
throw new NullPointerException();
if (n == capacity)
throw new IllegalStateException("Queue full");
enqueue(new Node<E>(e));
++n;
}
count.set(n);
} finally {
putLock.unlock();
}
}
ArrayBlockingQueue 队列使用示例
package com.huawei.apig.sdk.demo;
import java.util.concurrent.*;
public class ThreadPoolExecutorExample {
public static void main(String[] args) {
// 创建一个使用SynchronousQueue的线程池,并指定AbortPolicy作为拒绝策略
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
2,
0,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(20), // 创建一个容量为10的队列
new ThreadPoolExecutor.AbortPolicy());
// 提交任务给线程池
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("Thread " + Thread.currentThread().getName() + " is executing task " + taskId);
try {
// 模拟任务执行时间
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
// 关闭线程池
executor.shutdown();
try {
// 等待所有任务完成
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("All tasks completed.");
}
}
无限队列
LinkedBlockingQueue
LinkedBlockingQueue 由链表实现,队列可以指定队列的大小,也可以不指定大小。队列在接收任务的时候,会检测当前线程的数量,如果线程数小于配置的核心线程数,则创建线程处理任务;如果线程数等于配置的核心线程数,则任务存入队列中等待处理。
由此在使用 LinkedBlockingQueue 队列作为线程池队列时,maximumPoolSize 参数的设置是没有意义的,线程池中的最大线程数量就是 corePoolSize 参数值
LinkedBlockingQueue 队列构造函数
创建 LinkedBlockingQueue 队列的三种情况
1. 创建无限队列,默认队列的大小是 Integer.MAX_VALUE
2. 创建指定大小的队列,初始化头结点
3. 创建无限队列,默认队列的大小是 Integer.MAX_VALUE,并且进行队列初始化,入参是需要初始化的元素
/**
* Creates a {@code LinkedBlockingQueue} with a capacity of
* {@link Integer#MAX_VALUE}.
*/
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
/**
* Creates a {@code LinkedBlockingQueue} with the given (fixed) capacity.
*
* @param capacity the capacity of this queue
* @throws IllegalArgumentException if {@code capacity} is not greater
* than zero
*/
public LinkedBlockingQueue(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
last = head = new Node<E>(null);
}
/**
* Creates a {@code LinkedBlockingQueue} with a capacity of
* {@link Integer#MAX_VALUE}, initially containing the elements of the
* given collection,
* added in traversal order of the collection's iterator.
*
* @param c the collection of elements to initially contain
* @throws NullPointerException if the specified collection or any
* of its elements are null
*/
public LinkedBlockingQueue(Collection<? extends E> c) {
this(Integer.MAX_VALUE);
final ReentrantLock putLock = this.putLock;
putLock.lock(); // Never contended, but necessary for visibility
try {
int n = 0;
for (E e : c) {
if (e == null)
throw new NullPointerException();
if (n == capacity)
throw new IllegalStateException("Queue full");
enqueue(new Node<E>(e));
++n;
}
count.set(n);
} finally {
putLock.unlock();
}
}
LinkedBlockingQueue 队列使用示例
线程池中使用 LinkedBlockingQueue 队列,maxPoolSize 设置失效,设置成跟 corePoolSize 同样大小就好了;拒绝策略理论上也不会触发。
public class LinkedBlockingQueueExample {
@PostConstruct
public void init() {
// 线程池中使用 LinkedBlockingQueue 队列
ThreadFactory namedFactory = new ThreadFactoryBuilder().setNameFormat(
"threadListTestUseLinkedBlockingQueue").build();
ExecutorService executorService = new ThreadPoolExecutor(10,
10,
1,
TimeUnit.MINUTES,
new LinkedBlockingQueue<>(),
namedFactory,
new ThreadPoolExecutor.CallerRunsPolicy());
}
}
PriorityBlockingQueue
在Java中,PriorityBlockingQueue
是一个支持优先级排序的无界阻塞队列,它可以用于线程池中,以便按照任务的优先级来调度执行。虽然Java的标准线程池(如Executors
工厂类创建的线程池)通常不直接使用PriorityBlockingQueue
,但可以通过自定义线程池的方式来实现这一功能。
PriorityBlockingQueue 队列构造函数
/**
* Creates a {@code PriorityBlockingQueue} with the default
* initial capacity (11) that orders its elements according to
* their {@linkplain Comparable natural ordering}.
*/
public PriorityBlockingQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
/**
* Creates a {@code PriorityBlockingQueue} with the specified
* initial capacity that orders its elements according to their
* {@linkplain Comparable natural ordering}.
*
* @param initialCapacity the initial capacity for this priority queue
* @throws IllegalArgumentException if {@code initialCapacity} is less
* than 1
*/
public PriorityBlockingQueue(int initialCapacity) {
this(initialCapacity, null);
}
/**
* Creates a {@code PriorityBlockingQueue} with the specified initial
* capacity that orders its elements according to the specified
* comparator.
*
* @param initialCapacity the initial capacity for this priority queue
* @param comparator the comparator that will be used to order this
* priority queue. If {@code null}, the {@linkplain Comparable
* natural ordering} of the elements will be used.
* @throws IllegalArgumentException if {@code initialCapacity} is less
* than 1
*/
public PriorityBlockingQueue(int initialCapacity,
Comparator<? super E> comparator) {
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.lock = new ReentrantLock();
this.notEmpty = lock.newCondition();
this.comparator = comparator;
this.queue = new Object[initialCapacity];
}
/**
* Creates a {@code PriorityBlockingQueue} containing the elements
* in the specified collection. If the specified collection is a
* {@link SortedSet} or a {@link PriorityQueue}, this
* priority queue will be ordered according to the same ordering.
* Otherwise, this priority queue will be ordered according to the
* {@linkplain Comparable natural ordering} of its elements.
*
* @param c the collection whose elements are to be placed
* into this priority queue
* @throws ClassCastException if elements of the specified collection
* cannot be compared to one another according to the priority
* queue's ordering
* @throws NullPointerException if the specified collection or any
* of its elements are null
*/
public PriorityBlockingQueue(Collection<? extends E> c) {
this.lock = new ReentrantLock();
this.notEmpty = lock.newCondition();
boolean heapify = true; // true if not known to be in heap order
boolean screen = true; // true if must screen for nulls
if (c instanceof SortedSet<?>) {
SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
this.comparator = (Comparator<? super E>) ss.comparator();
heapify = false;
}
else if (c instanceof PriorityBlockingQueue<?>) {
PriorityBlockingQueue<? extends E> pq =
(PriorityBlockingQueue<? extends E>) c;
this.comparator = (Comparator<? super E>) pq.comparator();
screen = false;
if (pq.getClass() == PriorityBlockingQueue.class) // exact match
heapify = false;
}
Object[] a = c.toArray();
int n = a.length;
// If c.toArray incorrectly doesn't return Object[], copy it.
if (a.getClass() != Object[].class)
a = Arrays.copyOf(a, n, Object[].class);
if (screen && (n == 1 || this.comparator != null)) {
for (int i = 0; i < n; ++i)
if (a[i] == null)
throw new NullPointerException();
}
this.queue = a;
this.size = n;
if (heapify)
heapify();
}
PriorityBlockingQueue
队列使用
要使用 PriorityBlockingQueue
在线程池中管理任务,需要实现以下几步
1. 定义一个实现Runnable
或Callable
接口的任务类,并且这个类需要实现Comparable
接口,以便在队列中根据优先级进行排序
2. 创建一个PriorityBlockingQueue
实例,并将其作为任务队列传递给自定义的线程池
3. 实现一个自定义的线程池类,或者使用ThreadPoolExecutor
类,并将 PriorityBlockingQueue
作为任务队列传递给它
import java.util.concurrent.*;
// 定义一个实现Runnable接口的任务类,并实现Comparable接口
class PriorityTask implements Runnable, Comparable<PriorityTask> {
private final int priority;
private final String taskName;
public PriorityTask(int priority, String taskName) {
this.priority = priority;
this.taskName = taskName;
}
@Override
public void run() {
System.out.println("Executing task: " + taskName + " with priority: " + priority);
}
@Override
public int compareTo(PriorityTask other) {
// 任务优先级比较,优先级大的排在前面
return Integer.compare(other.priority, this.priority);
}
}
public class ThreadPoolExecutorExample {
public static void main(String[] args) {
// 创建一个PriorityBlockingQueue实例
PriorityBlockingQueue<Runnable> priorityQueue = new PriorityBlockingQueue<>();
ThreadPoolExecutor executorService = new ThreadPoolExecutor(1,
1,
1,
TimeUnit.MINUTES,
priorityQueue);
for (int i = 0; i < 10; i++) {
int priority = (int) (Math.random() * 10); // 随机生成优先级
System.out.println("random priority: " + priority);
executorService.execute(new PriorityTask(priority, "Task-" + i));
}
}
}