繁体   English   中英

Java:Producer = Consumer,如何知道何时停止?

[英]Java: Producer = Consumer, how to know when to stop?

我有几个工人,使用ArrayBlockingQueue。

每个worker从队列中获取一个对象,处理它,结果可以得到几个对象,这些对象将被放入队列中进行进一步处理。 所以,工人=生产者+消费者。

工人:

public class Worker implements Runnable
{
    private BlockingQueue<String> processQueue = null;

    public Worker(BlockingQueue<String> processQueue)
    {
        this.processQueue = processQueue;
    }

    public void run()
    {
        try
        {
            do
            {
                String item = this.processQueue.take();
                ArrayList<String> resultItems = this.processItem(item);

                for(String resultItem : resultItems)
                {
                    this.processQueue.put(resultItem);
                }
            }
            while(true);
        }
        catch(Exception)
        {
            ...
        }
    }

    private ArrayList<String> processItem(String item) throws Exception
    {
        ...
    }
}

主要:

public class Test
{
    public static void main(String[] args) throws Exception
    {
        new Test().run();
    }

    private void run() throws Exception
    {
        BlockingQueue<String> processQueue = new ArrayBlockingQueue<>(10000);
        processQueue.put("lalala");

        Executor service = Executors.newFixedThreadPool(100);
        for(int i=0; i<100; ++i)
        {
            service.execute(new Worker(processQueue));
        }
    }
}

当没有更多的工作时,什么是阻止工人的最佳方法?

首先,我想到的是定期检查队列中有多少项目以及当前正在处理多少项目。 如果两者都等于零,那么在ExecutorService上执行类似“shutdownNow()”的操作。 但我不确定这是最好的方法。

如果没有其他工作要做,请将一条消息放入队列中,然后让工作人员自行关闭。 这是防止数据损坏的好方法。

如果您需要通知另一个线程所有工作人员已经回家,您可以使用CountDownLatch来执行此操作。

听起来你有自己的解决方案 - 使用一个单独的正在进行的队列,其大小将是当前正在处理的项目数。 如果您使用约定访问任一队列的约定是在synchronized(theArrayBlockingQueue)块中,那么一切都应该很好。 特别是,在将项目移动到处理状态时,将其从ArrayBlockingQueue中删除,并将其添加到一块中的processingQueue中。

我稍微修改了你的代码,不确定这是否是你所期望的,但至少它终止了! 如果使用shutdownNow而不是shutdown工作程序将被中断,除非您将它们恢复工作,否则将退出而不保证队列为空。

public class Test {

    public static void main(String[] args) throws Exception {
        new Test().run();
    }

    private void run() throws Exception {
        BlockingQueue<String> processQueue = new ArrayBlockingQueue<>(10000);
        processQueue.put("lalalalalalalalalalalalala"); //a little longer to make sure there is enough to process

        ExecutorService service = Executors.newFixedThreadPool(100);
        for (int i = 0; i < 100; ++i) {
            service.execute(new Worker(processQueue));
        }
        service.shutdown(); //orderly shutdown = lets the tasks terminate what they are doing
        service.awaitTermination(1, TimeUnit.SECONDS); //blocks until all tasks have finished or throws TimeOutException if timeout is reached
    }

    public static class Worker implements Runnable {

        private BlockingQueue<String> processQueue = null;
        private int count = 0;

        public Worker(BlockingQueue<String> processQueue) {
            this.processQueue = processQueue;
        }

        @Override
        public void run() {
            try {
                do {
                    //tries to get something from the queue for 100ms and returns null if it could not get anything
                    String item = this.processQueue.poll(100, TimeUnit.MILLISECONDS);
                    if (item == null) break; //Ends the job because the queue was empty
                    count++;
                    List<String> resultItems = this.processItem(item);

                    for (String resultItem : resultItems) {
                        this.processQueue.put(resultItem);
                    }
                } while (true);
            } catch (InterruptedException e) {
                System.out.println("Interrupted");
                Thread.currentThread().interrupt();
            }
            if (count != 0) System.out.println(Thread.currentThread() + ": processed " + count + " entries");
        }

        private List<String> processItem(String item) { //let's put the string back less final character
            if (item.isEmpty()) {
                return Collections.<String> emptyList();
            } else {
                return Arrays.asList(item.substring(0, item.length() - 1));
            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM