Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.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 有可能对有界队列使用毒丸方法吗?_Java_Multithreading_Concurrency - Fatal编程技术网

Java 有可能对有界队列使用毒丸方法吗?

Java 有可能对有界队列使用毒丸方法吗?,java,multithreading,concurrency,Java,Multithreading,Concurrency,在Java并发实践手册(第156页)中,有一条关于毒丸方法的声明: 毒丸只能在未绑定队列中可靠工作 这是否意味着有界队列会导致死锁,还是与其他一些活动性问题有关? 它是否与生产商和客户的数量有关?如果队列有限,则可以阻止您添加毒丸 void close () throws InterruptedException { do { // Empty the queue. while ( queue.poll(0,TimeUnit.MILLISECONDS) != null ) {

在Java并发实践手册(第156页)中,有一条关于毒丸方法的声明:

毒丸只能在未绑定队列中可靠工作

这是否意味着有界队列会导致死锁,还是与其他一些活动性问题有关?
它是否与生产商和客户的数量有关?

如果队列有限,则可以阻止您添加毒丸

void close () throws InterruptedException {
  do {
    // Empty the queue.
    while ( queue.poll(0,TimeUnit.MILLISECONDS) != null ) {
      // Throw it away.
    }
    // Keep draining the queue 'till the pill is swallowed.
  } while (!queue.offer(STOP, 0, TimeUnit.MILLISECONDS)) ;
}

避免此问题的一种方法是,在添加毒药丸时,使有界队列再允许一个。

问题是,队列在关闭时可能已满

这取决于关闭时队列中数据的价值。你能负担得起把队列中的所有东西都扔掉吗

当需要关闭队列时,在添加毒药丸之前,应先排空队列

void close () throws InterruptedException {
  do {
    // Empty the queue.
    while ( queue.poll(0,TimeUnit.MILLISECONDS) != null ) {
      // Throw it away.
    }
    // Keep draining the queue 'till the pill is swallowed.
  } while (!queue.offer(STOP, 0, TimeUnit.MILLISECONDS)) ;
}
当然,如果队列中的项目有价值,您可能希望使用
drainto
并保存它们


还请记住,毒丸之后可能会有更多的项目添加到队列中,因为不仅队列可能已满,还可能有线程被阻止等待发送到队列。

@gstackoverflow:有界队列的主要问题是它具有最大容量,因此如果有界队列已满,当您想添加此“毒丸”时,将被阻止

请记住,毒丸必须立即放置,不能等到队列有一定的空间时才放置,,因为这种技术用于在异常发生时正常关闭消费者(否则存在更好的关闭消费者的技术)

编辑:一个例子讲了一千多句话,让我们看一个简单的例子(这个例子的所有学分在实践中都归Java并发),其中有一个生产者线程和一个消费者线程:

public class CrawlerThread extends Thread { //The Producer Thread
  public void run() {
    try {
      crawl(root);
    } catch (InterruptedException e) { /* fall through */ }
    finally {
      while (true) {
        try {
          queue.put(POISON);
          break;
        } catch (InterruptedException e1) { /* retry */ }
      }
    }
  }
  private void crawl(File root) throws InterruptedException {
    //some code
  }
}
public class IndexerThread extends Thread { //The consumer Thread
  public void run() {
    try {
      while (true) {
        File file = queue.take();
        if (file == POISON)
        break;
        else
        indexFile(file);
      }
    } catch (InterruptedException consumed) { }
  }
}
现在,当您检查Producer线程(CrawlerThread)时,您会看到毒丸被放置在运行结束时,或者在发生异常时处于更糟糕的情况下

现在假设您想使用一个有界队列作为生产者和消费者之间的接口,假设队列在时间t时已满,并且生产者在时间t时发生异常,生产者将无法将毒药丸放置在队列上,而不是让消费者线程关闭,使用者仍将等待元素进入队列。因此,如果使用有界队列,则不建议使用毒丸方法,因为它可能会导致意外结果。

我认为Java并发性的作者在实践中可能会这样说:

将新消息添加到完整的有界队列时,新消息或现有消息之一将被丢弃。因此,在毒药成为下一条可用信息之前,应用程序有可能永远持续滴下毒药


不过,可以添加逻辑。例如,我们可以强制执行始终添加有毒药片,而从不移除。在这种情况下,有界队列实际上可能会起作用。

好吧,每个等待能够在队列中添加某些项目的线程都可以被解锁,毒药丸仍将不在队列中。是否有具有可变容量的标准队列实现?另一种方法(假设阻塞队列)是使用对象池进行线程间通信,并确保每个队列的容量大于系统中可用对象的总数。所有队列都将始终有足够的空闲容量来容纳药丸。@Peter Lawrey Brian Goetz写道,这种技术根本不起作用。独立于消费者。不管怎样,我不明白如果我们使用有界queues@PeterLawrey Brian Goetz写道,这个问题只存在于有界队列中。我的问题是为什么有界队列不起作用reliably@PeterLawrey我认为回答这个问题的最好方法是提供一个有界队列不起作用但无界队列起作用的场景我不理解有界队列的问题它与公平性有关吗?请解释有界队列的使用问题你在哪里找到粗体文本?为什么线程总是不能被阻止?请看我的编辑,让我知道它是否对您的问题有帮助您是关于InterruptedException的吗?这可能发生在无限队列的情况下,无论如何,添加到队列需要一些时间,也可能发生争用,我仍然看不出区别其他中断如何?如果由于磁盘已满而发生io异常,并且您必须等待10分钟才能将避孕药放入有界队列,是否可以接受?有界队列上也可能发生任何中断。若您想添加大量的元素,那个么在无界队列上可能会发生争用和显著的冲突