一旦管理器停止,最好的拒绝方式会添加到队列中

时间:2011-11-18 23:34:28

标签: java multithreading synchronization queue

关于阻止所有添加的最佳方法的任何想法一旦被调用了吗?

另外,这是我第一次使用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);
                }
            }
        }
    }
}

5 个答案:

答案 0 :(得分:1)

首先不要默默地捕获InterruptedException ,至少在该捕获中重置Thread.currentThread().interrupt();的标志

第二,有更好地调整的线程安全队列实现检查java.util.concurrent

并且线程可能会在Tunpark()删除最后一个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);
                }
            }
        }
    }
}