1

我有一组 12 个线程并行执行工作(Runnable)。本质上,每个线程执行以下操作:

Runnable r;

while (true) {
    synchronized (work) {
        while (work.isEmpty()) {
            work.wait();
        }
        r = work.removeFirst();
    }
    r.execute();
}

添加工作如下:

Runnable r = ...;

synchronized (work) {
    work.add(r);
    work.notify();
}

当有新作品可用时,它会被添加到列表中并通知锁定。如果有线程在等待,它就会被唤醒,所以它可以执行这个工作。

问题就在这里。当一个线程被唤醒时,很有可能另一个线程会执行这个工作。当后一个线程完成其先前的工作并重新进入while(true)循环时,就会发生这种情况。工作动作越小/越短,发生这种情况的可能性就越大。

这意味着我正在无缘无故地唤醒一个线程。由于我需要高吞吐量,我相信这种行为会降低性能。

你会如何解决这个问题?理论上,我需要一种机制来取消挂起的线程唤醒通知。当然,这在 Java 中是不可能的。

我考虑为每个线程引入一个工作列表。不是将工作推入一个单独的列表,而是将工作分布在 12 个工作列表中。但我相信这会带来其他问题。例如,一个线程可能有很多待处理的工作,而另一个线程可能没有待处理的工作。从本质上讲,我相信提前将工作分配给特定线程的解决方案可能会变得非常复杂并且是次优的。

谢谢!

4

2 回答 2

2

你正在做的是一个线程池。看看 pre java-5 并发框架,那里的 PooledExecutor 类:http: //gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html

于 2013-04-06T16:55:10.833 回答
0

除了我之前的答案 - 另一个解决方案。这个问题让我很好奇。

在这里,我添加了一个带有 volatile 布尔值的检查。

它并不能完全避免无用唤醒线程的情况,但有助于避免这种情况。实际上,如果没有额外的限制,例如“我们知道 100 毫秒后最有可能完成一项工作”,我看不出如何完全避免这种情况。

volatile boolean free = false;

while (true) {
    synchronized (work) {
        free = false;               // new rev.2
        while (work.isEmpty()) {
            work.wait();
        }
        r = work.removeFirst();
    }
    r.execute();
    free = true;        // new
}

--

synchronized (work) {
    work.add(r);
    if (!free) {         // new
         work.notify();
    }                    // new
    free = false;        // new rev.2
}
于 2013-04-06T17:38:23.503 回答