Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:Producer=Consumer,如何知道何时停止?_Java_Producer Consumer_Blockingqueue - Fatal编程技术网

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

Java:Producer=Consumer,如何知道何时停止?,java,producer-consumer,blockingqueue,Java,Producer Consumer,Blockingqueue,我有几个工人,他们使用ArrayBlockingQueue 每个工人从队列中取出一个对象,对其进行处理,结果可以得到多个对象,这些对象将被放入队列中进行进一步处理。因此,工人=生产者+消费者 工人: public class Worker implements Runnable { private BlockingQueue<String> processQueue = null; public Worker(BlockingQueue<String>

我有几个工人,他们使用ArrayBlockingQueue

每个工人从队列中取出一个对象,对其进行处理,结果可以得到多个对象,这些对象将被放入队列中进行进一步处理。因此,工人=生产者+消费者

工人:

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));
        }
    }
}
公共类工作程序实现可运行
{
private BlockingQueue processQueue=null;
公共工作者(阻塞队列处理队列)
{
this.processQueue=processQueue;
}
公开募捐
{
尝试
{
做
{
String item=this.processQueue.take();
ArrayList resultItems=此.processItem(项);
for(字符串resultItem:resultItems)
{
this.processQueue.put(resultItem);
}
}
虽然(正确);
}
捕获(例外)
{
...
}
}
私有ArrayList processItem(字符串项)引发异常
{
...
}
}
Main:

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));
        }
    }
}
公共类测试
{
公共静态void main(字符串[]args)引发异常
{
新建测试().run();
}
private void run()引发异常
{
BlockingQueue processQueue=new ArrayBlockingQueue(10000);
processQueue.put(“lalala”);
Executor服务=Executors.newFixedThreadPool(100);

对于(int i=0;i如果没有更多的工作要做,请在队列中输入这样一条消息,并让工作人员在自己方便的时候关闭自己。这是防止数据损坏的好方法


如果您需要通知另一个线程所有的工作线程都已回家,您可以使用一个线程来完成此操作。

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

我稍微修改了您的代码,不确定这是否是您所期望的,但至少它会终止!如果您使用
shutdownow
In停止
关机
您的工作人员将被中断,除非您让他们重新开始工作,否则他们将退出,但不能保证队列是空的

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));
            }
        }
    }
}
公共类测试{
公共静态void main(字符串[]args)引发异常{
新建测试().run();
}
private void run()引发异常{
BlockingQueue processQueue=new ArrayBlockingQueue(10000);
processQueue.put(“lalala”);//再长一点,以确保有足够的时间进行处理
ExecutorService=Executors.newFixedThreadPool(100);
对于(int i=0;i<100;++i){
执行(新工作进程(processQueue));
}
service.shutdown();//有序关机=允许任务终止正在执行的操作
service.waitTermination(1,TimeUnit.SECONDS);//阻塞直到所有任务完成,或者在达到超时时抛出TimeOutException
}
公共静态类辅助程序实现可运行{
private BlockingQueue processQueue=null;
私有整数计数=0;
公共工作者(阻塞队列处理队列){
this.processQueue=processQueue;
}
@凌驾
公开募捐{
试一试{
做{
//尝试从队列中获取100ms的内容,如果无法获取任何内容,则返回null
String item=this.processQueue.poll(100,TimeUnit.ms);
if(item==null)break;//结束作业,因为队列为空
计数++;
List resultItems=this.processItem(项目);
for(字符串resultItem:resultItems){
this.processQueue.put(resultItem);
}
}虽然(正确);
}捕捉(中断异常e){
系统输出打印项次(“中断”);
Thread.currentThread().interrupt();
}
if(count!=0)System.out.println(Thread.currentThread()+”:已处理的“+count+”条目);
}
private-List-processItem(String-item){//让我们把字符串放回最后一个字符以下
if(item.isEmpty()){
返回集合。emptyList();
}否则{
返回Arrays.asList(item.substring(0,item.length()-1));
}
}
}
}

更有趣的问题是,您如何保护自己不受循环模式的影响,很明显,队列在某些情况下可能会自我复制。您能否澄清一下用例?您是希望应用程序在队列为空时自行终止,还是希望当向应用程序发出关闭请求时,只有在队列关闭后才会终止是空的吗?@Osw,这里的“循环模式”是什么意思?@Handerson,是的,我想在没有更多工作时终止应用程序本身。@Olegolovanov如果你能发布一个简单的例子(与制作人、消费者、执行者一起)说明你试图实现的目标,可能更容易理解你的问题所在。我不能使用“毒丸”因为我没有一个制作人知道什么时候他没有更多的工作要做。关于倒计时闩锁:为了做到这一点,每个工人都必须知道什么时候没有更多的工作:)谢谢你的回答:)我真的需要“processingQueue”或AtomicInteger(表示当前正在处理的项目数量)就足够了吗?可能是我不知道什么。我喜欢用数据结构而不是线程的局部变量来表示“状态”。例如,我可以作为控制线程,在ArrayBlockingQueue上同步,杀死所有线程