关于阻止所有添加的最佳方法的任何想法一旦被调用了吗?
另外,这是我第一次使用LockSupport这是在等待新队列时处理阻塞队列的最佳方法吗?
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.LockSupport;
/**
*
* @author Marc D. Benstein
*/
public abstract class AbstractWorkerQueue<T> implements AutoCloseable {
private final List<T> queue;
private final Thread thread;
public AbstractWorkerQueue(String threadName) {
queue = Collections.synchronizedList(new LinkedList<T>());
thread = new Thread(new QueueManager(), threadName);
}
public void offer(T item) {
synchronized (queue) {
queue.add(item);
}
LockSupport.unpark(thread);
}
public void clear() {
synchronized (queue) {
queue.clear();
}
}
@Override
public void close() {
stop();
}
protected void start() {
thread.start();
}
protected void stop() {
offer(null);
try {
thread.join();
} catch (InterruptedException ex) {
}
}
protected abstract void process(T item);
private class QueueManager implements Runnable {
@Override
public void run() {
while (true) {
T item = null;
synchronized (queue) {
if (!(queue.isEmpty())) {
item = queue.remove(0);
if (item == null) {
// null dentotes end of queue
return;
}
}
}
if (item != null) {
process(item);
} else {
LockSupport.park(thread);
}
}
}
}
}
答案 0 :(得分:1)
首先不要默默地捕获InterruptedException ,至少在该捕获中重置Thread.currentThread().interrupt();
的标志
第二,有更好地调整的线程安全队列实现检查java.util.concurrent
包
并且线程可能会在T
在unpark()
删除最后一个QueueManager
之后立即添加park()
并致电wait
。你最好关闭同步块内的notify
和{{1}}队列
答案 1 :(得分:0)
抛出IllegalStateException
,也许是其中的一个子类。
答案 2 :(得分:0)
将新实例volatile变量isStopped添加到AbstractWorkerQueue类,默认值为false。调用stop方法后,将标志设置为true。
您可以在任何后续的offer()请求中抛出IllegalStateException,或者在不将其添加到队列的情况下返回。
答案 3 :(得分:0)
我现在无法测试,但如何:
volatile boolean closed = false;
public void offer(T item) {
if ( !closed ) {
synchronized (queue) {
queue.add(item);
if ( item == null ) {
closed = true;
}
}
// Not sure if this should be outside or inside the if.
LockSupport.unpark(thread);
}
}
已添加:我认为竞争条件的唯一副作用是在null之后将少量额外项目发布到队列中。只要你在消费者中处理(你似乎),那就不应该有问题了。但是,如果这是一个问题,你可以这样做:
volatile boolean closed = false;
public void offer(T item) {
if ( !closed ) {
synchronized (queue) {
if ( !closed ) {
queue.add(item);
if ( item == null ) {
closed = true;
}
}
}
// Not sure if this should be outside or inside the if.
LockSupport.unpark(thread);
}
}
答案 4 :(得分:0)
简化版代码。
注意提供现在返回布尔值,如标准java.util.Queue
。我更喜欢Throwable for close flag,即使我不在这里使用任何东西,它对调试目的来说非常有用,可以记录调用close()的时刻。
除了删除LinkedList和synchronized。
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.LockSupport;
public abstract class AbstractWorkerQueue<T> {
private final ConcurrentLinkedQueue<T> queue;
private final Thread thread;
private volatile RuntimeException closed;//records the closure point
public AbstractWorkerQueue(String threadName) {
queue = new ConcurrentLinkedQueue<T>();
thread = new Thread(new QueueManager(), threadName);
}
public boolean offer(T item) {
if (closed!=null)
return false;
queue.offer(item);
LockSupport.unpark(thread);
return true;
}
public void clear() {
queue.clear();//this may not be carried properly
}
public void close() {
stop();
}
protected void start() {
thread.start();
}
protected void stop() {
if (closed!=null)
return;
closed = new IllegalStateException("closure point");//should be CAS'd but meh
LockSupport.unpark(thread);
try {
thread.join();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
protected abstract void process(T item);
private class QueueManager implements Runnable {
@Override
public void run() {
while (closed==null) {
final T item = queue.poll();
if (item != null) {
process(item);
} else {
LockSupport.park(thread);
}
}
}
}
}