我知道这已经是一个老问题了,但是在阅读了问题和答案之后,我无法帮助自己,我希望你觉得这很有用。
关于在通知其他等待线程之前检查队列实际上是满的还是空的,你错过了一些东西,这两个方法都是方法,这意味着一次只有一个线程可以进入这些方法之一,但这不会阻止它们一起工作,所以如果一个线程a已经进入了方法,另一个线程b仍然可以在线程a退出之前进入并开始执行方法中的指令。 所以这个设计会让开发人员感觉更安全一点,因为你无法知道未来的cpu上下文切换是否会发生,或者什么时候会发生。put (T t)
T get()
synchronized
put (T t)
T get()
put (T t)
double-checking
一种更好和更推荐的方法是使用和:Reentrant Locks
Conditions
我已经编辑了此链接的源代码
Condition isFullCondition;
Condition isEmptyCondition;
Lock lock;
public BQueue() {
this(Integer.MAX_VALUE);
}
public BQueue(int limit) {
this.limit = limit;
lock = new ReentrantLock();
isFullCondition = lock.newCondition();
isEmptyCondition = lock.newCondition();
}
public void put (T t) {
lock.lock();
try {
while (isFull()) {
try {
isFullCondition.await();
} catch (InterruptedException ex) {}
}
q.add(t);
isEmptyCondition.signalAll();
} finally {
lock.unlock();
}
}
public T get() {
T t = null;
lock.lock();
try {
while (isEmpty()) {
try {
isEmptyCondition.await();
} catch (InterruptedException ex) {}
}
t = q.poll();
isFullCondition.signalAll();
} finally {
lock.unlock();
}
return t;
}
使用这种方法不需要 ,因为对象在两个方法之间共享,这意味着一次只有一个线程 a 或 b 可以输入这些方法中的任何一个,这与创建不同监视器的同步方法不同,并且只有那些因为队列已满而等待的线程才会在有更多空间时收到通知, 对于等待的线程也是如此,因为队列是空的,这将导致更好的CPU利用率。你可以在这里找到更详细的源代码示例double checking
lock
我认为从逻辑上讲,在之前进行额外的检查没有坏处。notifyAll()
你可以简单地一旦你把/从队列中得到一些东西。一切仍然可以工作,并且您的代码更短。但是,在调用 之前,检查是否有人可能正在等待(通过检查是否达到队列边界)也没有坏处。这个额外的逻辑片段节省了不必要的调用。notifyAll()
notifyAll()
notifyAll()
这只取决于您想要更短,更干净的代码,或者您希望代码更有效地运行。(尚未研究 的实现。如果这是一个廉价的操作,如果没有人等待,那么对于额外的检查来说,性能提升可能并不明显)notifyAll()
-
-
如何检测我的方法在等待什么? 我在Java中有一个调用其他几个方法的方法。此方法是从固定线程池中的多个线程调用的。工作线程数与可用处理器(内核)数相同。 当我使用 VisualVM 分析程序执行时,时间和时间非常短,但
-
Java 服务器的单线程池还是多线程池?[已关闭] 我正在编写一个相当复杂的Java服务器应用程序,除了通常的请求 - 响应处理之外,它还具有重要的后台处理部分。一些后台处理是使用Quartz框架以类似cron的方式完成的。
-
-
从直方图计算平均值和百分位数? 我编写了一个计时器,它将测量任何多线程应用程序中特定代码的性能。在下面的计时器中,它还将使用 x 毫秒的调用数填充地图。我将使用此映射作为直方图的一部分进行进一步分析,例如调