Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.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 生产者-消费者问题 生产者是有限的,消费者也是有限的。 问题在于何时停止,而不是如何运行 通信可以通过任何类型的阻塞队列进行。 不能依赖于对队列下毒(PriorityBlockingQueue) 无法依赖于锁定队列(SynchronousQueue) 不能完全依赖报价/投票(SynchronousQueue) 可能还有更奇特的队列存在_Java_Concurrency_Clojure - Fatal编程技术网

Java 生产者-消费者问题 生产者是有限的,消费者也是有限的。 问题在于何时停止,而不是如何运行 通信可以通过任何类型的阻塞队列进行。 不能依赖于对队列下毒(PriorityBlockingQueue) 无法依赖于锁定队列(SynchronousQueue) 不能完全依赖报价/投票(SynchronousQueue) 可能还有更奇特的队列存在

Java 生产者-消费者问题 生产者是有限的,消费者也是有限的。 问题在于何时停止,而不是如何运行 通信可以通过任何类型的阻塞队列进行。 不能依赖于对队列下毒(PriorityBlockingQueue) 无法依赖于锁定队列(SynchronousQueue) 不能完全依赖报价/投票(SynchronousQueue) 可能还有更奇特的队列存在,java,concurrency,clojure,Java,Concurrency,Clojure,在另一个(可能是惰性的)序列上创建排队序列。排队的人 seq将在背景中生成一个具体的seq,并且可以达到 n消费者面前的商品。n或q可以是整数n缓冲区 大小,或java.util.concurrent BlockingQueue的实例。笔记 如果读卡器超前于序列,则序列的读取可能会被阻塞 制片人 我迄今为止的尝试+一些测试: 欢迎使用Java或Clojure解决方案。类读取器{ class Reader { private final ExecutorService ex = Exe

在另一个(可能是惰性的)序列上创建排队序列。排队的人 seq将在背景中生成一个具体的seq,并且可以达到 n消费者面前的商品。n或q可以是整数n缓冲区 大小,或java.util.concurrent BlockingQueue的实例。笔记 如果读卡器超前于序列,则序列的读取可能会被阻塞 制片人

我迄今为止的尝试+一些测试:

欢迎使用Java或Clojure解决方案。

类读取器{
class Reader {

    private final ExecutorService ex = Executors.newSingleThreadExecutor();
    private final List<Object> completed = new ArrayList<Object>();
    private final BlockingQueue<Object> doneQueue = new LinkedBlockingQueue<Object>();
    private int pending = 0;

    public synchronized Object take() {
        removeDone();
        queue();
        Object rVal;
        if(completed.isEmpty()) {
            try {
                rVal = doneQueue.take();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            pending--;
        } else {
            rVal = completed.remove(0);
        }
        queue();
        return rVal;
    }

    private void removeDone() {
        Object current = doneQueue.poll();
        while(current != null) {
            completed.add(current);
            pending--;
            current = doneQueue.poll();
        }
    }

    private void queue() {
        while(pending < 10) {
            pending++;
            ex.submit(new Runnable() {

                @Override
                public void run() {
                    doneQueue.add(compute());
                }

                private Object compute() {
                    //do actual computation here
                    return new Object();
                }
            });
        }
    }
}
private final ExecutorService ex=Executors.newSingleThreadExecutor(); 私有最终列表已完成=新建ArrayList(); private final BlockingQueue doneQueue=new LinkedBlockingQueue(); 私有int挂起=0; 公共同步对象take(){ 去除酮(); 队列(); 对象rVal; if(completed.isEmpty()){ 试一试{ rVal=doneQueue.take(); }捕捉(中断异常e){ 抛出新的运行时异常(e); } 待定--; }否则{ rVal=已完成。删除(0); } 队列(); 返回rVal; } 私有无效删除一个(){ 当前对象=doneQueue.poll(); while(当前!=null){ 已完成。添加(当前); 待定--; current=doneQueue.poll(); } } 私有无效队列(){ 同时(待定<10){ 挂起++; ex.submit(新的可运行(){ @凌驾 公开募捐{ add(compute()); } 私有对象计算(){ //在这里进行实际计算 返回新对象(); } }); } } }
类读取器{
private final ExecutorService ex=Executors.newSingleThreadExecutor();
私有最终列表已完成=新建ArrayList();
private final BlockingQueue doneQueue=new LinkedBlockingQueue();
私有int挂起=0;
公共同步对象take(){
去除酮();
队列();
对象rVal;
if(completed.isEmpty()){
试一试{
rVal=doneQueue.take();
}捕捉(中断异常e){
抛出新的运行时异常(e);
}
待定--;
}否则{
rVal=已完成。删除(0);
}
队列();
返回rVal;
}
私有无效删除一个(){
当前对象=doneQueue.poll();
while(当前!=null){
已完成。添加(当前);
待定--;
current=doneQueue.poll();
}
}
私有无效队列(){
同时(待定<10){
挂起++;
ex.submit(新的可运行(){
@凌驾
公开募捐{
add(compute());
}
私有对象计算(){
//在这里进行实际计算
返回新对象();
}
});
}
}
}

恐怕这不是一个确切的答案,但有几句话和更多的问题。我的第一个答案是:使用
clojure.core/seque
。制作人需要以某种方式传达seq的结尾,以便消费者知道何时停止,我假设生产的元素的数量事先不知道。为什么不能使用EOS标记(如果这就是队列中毒的意思)

如果我正确理解了您的可选
序列
实现,当元素从您的函数外的队列中取出时,它将中断,因为
通道
q
在这种情况下会失步:通道将容纳比
q
中的元素更多的
(.take q)
元素,使其阻塞。可能有一些方法可以确保
channel
q
始终同步,但这可能需要实现您自己的
Queue
类,它增加了太多的复杂性,我怀疑它是否值得


此外,您的实现没有区分正常EOS和由于线程中断而导致的异常队列终止,这取决于您使用它的目的,您可能想知道哪个是哪个。就个人而言,我不喜欢以这种方式使用异常-在异常情况下使用异常,而不是在正常的流控制中使用异常。

恐怕这不是一个确切的答案,但有几句话和更多的问题。我的第一个答案是:使用
clojure.core/seque
。制作人需要以某种方式传达seq的结尾,以便消费者知道何时停止,我假设生产的元素的数量事先不知道。为什么不能使用EOS标记(如果这就是队列中毒的意思)

如果我正确理解了您的可选
序列
实现,当元素从您的函数外的队列中取出时,它将中断,因为
通道
q
在这种情况下会失步:通道将容纳比
q
中的元素更多的
(.take q)
元素,使其阻塞。可能有一些方法可以确保
channel
q
始终同步,但这可能需要实现您自己的
Queue
类,它增加了太多的复杂性,我怀疑它是否值得

此外,您的实现不区分正常EOS和