Java Concurrency JDK 1.6:忙碌等待比信令好吗?有效的Java#51
Joshua Bloch的“Effective
Java”,第51项不是依赖于线程调度程序,也不是在可运行状态下不必要地保留线程.引用文字:
然后继续显示忙碌等待的微基准测试与正确使用信号.在书中,忙碌等待执行17次往返/秒,而等待/通知版本每秒执行23,000次往返. 但是,当我在JDK 1.6上尝试相同的基准测试时,我看到恰恰相反 – 忙等待是760K往返/秒,而等待/通知版本是53.3K往返/秒 – 也就是说,等待/通知应该是~1400时间更快,但结果慢了约13倍? 我知道繁忙的等待并不好,信号仍然更好 – 忙等待版本的CPU利用率约为50%,而等待/通知版本的停留率约为30% – 但有没有解释数字的东西? 如果它有帮助,我在Win 7 x64(核心i5)上运行JDK1.6(32位). 更新:来源如下.要运行繁忙的工作台,请将PingPongQueue的基类更改为BusyWorkQueue abstract class SignalWorkQueue { private final List queue = new LinkedList(); private boolean stopped = false; protected SignalWorkQueue() { new WorkerThread().start(); } public final void enqueue(Object workItem) { synchronized (queue) { queue.add(workItem); queue.notify(); } } public final void stop() { synchronized (queue) { stopped = true; queue.notify(); } } protected abstract void processItem(Object workItem) throws InterruptedException; private class WorkerThread extends Thread { public void run() { while (true) { // Main loop Object workItem = null; synchronized (queue) { try { while (queue.isEmpty() && !stopped) queue.wait(); } catch (InterruptedException e) { return; } if (stopped) return; workItem = queue.remove(0); } try { processItem(workItem); // No lock held } catch (InterruptedException e) { return; } } } } } // HORRIBLE PROGRAM - uses busy-wait instead of Object.wait! abstract class BusyWorkQueue { private final List queue = new LinkedList(); private boolean stopped = false; protected BusyWorkQueue() { new WorkerThread().start(); } public final void enqueue(Object workItem) { synchronized (queue) { queue.add(workItem); } } public final void stop() { synchronized (queue) { stopped = true; } } protected abstract void processItem(Object workItem) throws InterruptedException; private class WorkerThread extends Thread { public void run() { final Object QUEUE_IS_EMPTY = new Object(); while (true) { // Main loop Object workItem = QUEUE_IS_EMPTY; synchronized (queue) { if (stopped) return; if (!queue.isEmpty()) workItem = queue.remove(0); } if (workItem != QUEUE_IS_EMPTY) { try { processItem(workItem); } catch (InterruptedException e) { return; } } } } } } class PingPongQueue extends SignalWorkQueue { volatile int count = 0; protected void processItem(final Object sender) { count++; SignalWorkQueue recipient = (SignalWorkQueue) sender; recipient.enqueue(this); } } public class WaitQueuePerf { public static void main(String[] args) { PingPongQueue q1 = new PingPongQueue(); PingPongQueue q2 = new PingPongQueue(); q1.enqueue(q2); // Kick-start the system // Give the system 10 seconds to warm up try { Thread.sleep(10000); } catch (InterruptedException e) { } // Measure the number of round trips in 10 seconds int count = q1.count; try { Thread.sleep(10000); } catch (InterruptedException e) { } System.out.println(q1.count - count); q1.stop(); q2.stop(); } } 解决方法
在您的测试中,队列连续获取新项目,因此忙碌等待实际等待很少.
如果队列每1ms获得一个新项目,您可以看到忙等待将花费大部分时间来刻录CPU.它会减慢应用程序的其他部分. 所以这取决于.如果你忙着等待用户输入,那肯定是错的;而像AtomicInteger这样的无锁数据结构中的繁忙等待肯定是好的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |