Thread.yield()有更好的解决方案吗? [英] Is there a better solution to Thread.yield()?

查看:176
本文介绍了Thread.yield()有更好的解决方案吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个扩展ArrayBlockingQueue的CloseableBlockingQueue:

I have created a CloseableBlockingQueue extending ArrayBlockingQueue:

private static class CloseableBlockingQueue<E> extends ArrayBlockingQueue<E> {
// Flag indicates closed state.
private volatile boolean closed = false;

public CloseableBlockingQueue(int queueLength) {
  super(queueLength);
}

/***
 * Shortcut to do nothing if closed.
 */
@Override
public boolean offer(E e) {
  return closed ? true : super.offer(e);
}

/***
 * Shortcut to do nothing if closed.
 */
@Override
public void put(E e) throws InterruptedException {
  if (!closed) {
    super.put(e);
  }
}

/***
 * Shortcut to do nothing if closed.
 */
@Override
public E poll() {
  return closed ? null : super.poll();
}

/***
 * Shortcut to do nothing if closed.
 * @throws InterruptedException 
 */
@Override
public E poll(long l, TimeUnit tu) throws InterruptedException {
  return closed ? null : super.poll(l, tu);
}

/***
 * Mark me as closed and clear the queue.
 */
void close() {
  closed = true;
  // There could be more threads blocking on my queue than there are slots 
  // in the queue. We therefore MUST loop.
  do {
    // so keep clearing
    clear();
    /* Let others in ... more specifically, any collectors blocked on the 
     * queue should now unblock and finish their put.
     * 
     * Subsequent puts should shortcut but it is the waiting ones I need
     * to clear.
     */
    Thread.yield();
    /* Debug code.
    // Did yield achieve?
    if (!super.isEmpty()) {
     * This DOES report success.
      log("! Thread.yield() successful");
    }
     * 
     */
    // Until all are done.
  } while (!super.isEmpty());
}

/***
 * isClosed
 * 
 * @return true if closed.
 */
boolean isClosed() {
  return closed;
}
}

我关注的是它正在尝试的close方法重新启动队列中阻塞的任何线程。我使用Thread.yield()来尝试,但是我看到过这样的引用,表明这种技术可能并不总是有效,因为无法保证在收益期间任何其他被阻塞的线程都会被唤醒。

My concern is with the close method where it is trying to kick back into life any threads that are blocked on the queue. I use Thread.yield() to attempt that but I have seen references that suggest that this technique may not always work because there is no guarantee that any other blocked threads will be woken up during a yield.

该队列用于将多个线程的输出集中到一个流中。与队列中的插槽相比,可以轻松地提供更多线程,因此队列很可能已满并且当它关闭时,有几个线程阻塞它。

The queue is used to concentrate the output of multiple threads into a single stream. There can easily be many more threads feeding it than there are slots in the queue so it is quite possible for the queue to be full AND several threads are blocking on it when it is closed.

我欢迎你的想法。

已添加

感谢Tom's我在下面的建议中重构:

Thanks to Tom's suggestion below I have refactored to:


  • 保留可能阻塞的所有线程的集合。

  • 关闭时,中断所有这些。

BTW:由于线程集合主要用于添加对象,几乎立即删除同样的对象我从 http:/中获取了Doug Lea令人印象深刻的ConcurrentDoublyLinkedList的副本/www.java2s.com/Code/Java/Collections-Data-Structure/ConcurrentDoublyLinkedList.htm 并添加了几种方法以允许我保持添加的节点。删除应该是O(1)而不是O(n)。

BTW: Since the thread collection is used mostly for adding an object and almost immediately removing the same object I took a copy of Doug Lea's impressive ConcurrentDoublyLinkedList from http://www.java2s.com/Code/Java/Collections-Data-Structure/ConcurrentDoublyLinkedList.htm and added a couple of methods to allow me to keep hold of the added node. Removal should then be O(1) instead of O(n).

保罗

推荐答案

我认为yield()根本不会影响队列中阻塞的线程。

I don't think yield() would affect the threads blocked on the queue at all.

如果可以跟踪等待的线程(鉴于你正在包装阻塞方法,应该是直截了当的。你可以在关闭时调用它们的中断()。

If you can keep track of the waiting threads (should be straightforward given you're wrapping the blocking methods). You could call interrupt() on them when you close.

看到这个问题: ArrayBlockingQueue - 如何中断正在使用.take()方法的线程

这篇关于Thread.yield()有更好的解决方案吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆