Sometimes it is necessary to impose certain order on the tasks in a threadpool. Issue 206 of the JavaSpecialists newsletter presents one such case: we have multiple connections from which we read using NIO. We need to ensure that events from a given connection are executed in-order but events between different connections can be freely mixed.
I would like to present a similar but slightly different situation: we have N clients. We would like to execute events from a given client in the order they were submitted, but events from different clients can be mixed freely. Also, from time to time, there are “rollup” tasks which involve more than one client. Such tasks should block the tasks for all involved clients (but not more!). Let’s see a diagram of the situation:

As you can see tasks from client A and client B are happily processed in parallel until a “rollup” task comes along. At that point no more tasks of type A or B can be processed but an unrelated task C can be executed (provided that there are enough threads). The skeleton of such an executor is available in my repository. The centerpiece is the following interface:
public interface OrderedTask extends Runnable {
boolean isCompatible(OrderedTask that);
}
Using this interface the threadpool decides if two tasks may be run in parallel or not (A and B can be run in parallel if A.isCompatible(B) && B.isComaptible(A)). These methods should be implemented in a fast, non locking and time-invariant manner.
The algorithm behind this threadpool is as follows:

More information about the implementation:
Have fun with the source code! (maybe some day I’ll find the time to remove all the rough edges).
* somewhat of a misnomer, since there are still locks, only at a lower – CPU not OS – level, but this is the accepted terminology
** – benchmarking indicated this to be the most performant solution. This was inspired from the implementation of the ThreadPoolExecutor.
Meta: this post is part of the Java Advent Calendar and is licensed under the Creative Commons 3.0 Attribution license. If you like it, please spread the word by sharing, tweeting, FB, G+ and so on! Want to write for the blog? We are looking for contributors to fill all 24 slot and would love to have your contribution! Contact Attila Balazs to contribute!
]]>Testing multi-threaded code is hard. The main problem is that you
invoke your assertions either too soon (and they fail for no good
reason) or too late (in which case the test runs for a long time,
frustrating you). A possible solution is to declare an interface like
the following:
interface ActivityWatcher {
void before();
void after();
void await(long time, TimeUnit timeUnit) throws InterruptedException, TimeoutException;
}
It is intended to be used as follows:
The net result is that when the counter is zero, all your asynchronous tasks have executed and you can run your assertions. See the example code. A couple more considerations:
One thing the above code doesn’t do is collecting exceptions: if the
exceptions happen on different threads than the one executing the
testrunner, they will just die and the testrunner will happily report
that the tests passs. You can work around this in two ways:
collect(Throwable)” method which gets called with the uncaught exceptions and “await” rethrows them.Implementing this is left as an exercise to the reader :-).![]()
To illustrate the problem, I’ve created a small program. It does the following:
Everything looks fine and dandy, right? The object isn’t changed (apparently) after being handed of to the threadpool, yet sometimes wrong answers still appear (it takes around ~30 min on my laptop for such an event). So what are the lessons here?
getTime() after setting the values, which preemptively normalizes the internal representation. Of course the proper solution would be to pass around truly immutable objects (like timestamps or value objects from Joda Time).I was profiling a rather old legacy codebase (since the first rule of performance optimization is “profile it” with the close second of “have clear goals in mind” – but that’s an other post) and – after optimizing the first few hotspots, Thread.yield appeared at the top of the most timely methods. I was intrigued, since I didn’t use yield since I wrote “cooperative multitasking” programs for Windows 3.1 in VB 3 (and I’m not a big Python programmer either). So I scoured the ‘net for Information on why/when you should use Thread.yield, but came up with relative few pieces of information:
So I’ve decided to do some micro-benchmarks. They consisted of a producer and a consumer thread, connected by an unbounded queue (a LinkedBlockingQueue to be more exact) and I measure the number of items produced / consumer in 10 seconds. The first set of measurements were performed on a dual-core machine, while the second set in a VM to simulate a single-CPU system (it’s kind of ironic that one has to perform simulation to evaluate single-core systems). This isn’t meant to be a performance, evaluation, thus all the numbers are normalized to the produced/direct number.
| 2 CPUs | 1 CPU | |||
|---|---|---|---|---|
| Direct | 1 | 1 | 1 | 0.06 |
| Thread.yield() | 0.12 | 0.12 | 0.04 | 0.04 |
| Thread.sleep(0) | 0.1 | 0.1 | 0.04 | 0.04 |
| Priority – 1 | 0.81 | 0.81 | 1 | 0.05 |
(My) conclusions:
Finally I would like to leave you with the following short (~30 min) presentation about performance optimization on the JVM: Making every millisecond count! JVM performance tuning in the real-world.
]]>priv.addAll(common);
Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException at java.lang.System.arraycopy(Native Method) at java.util.ArrayList.toArray(Unknown Source) at java.util.ArrayList.addAll(Unknown Source) at TestConcurrentList$ConsumeThread.run(TestConcurrentList.java:34)
Answer: because of bad synchronization. The scenario is the following: one thread is continuously modifying the list “common” while the second thread tries to perform the “addAll” operation on it. The testcode is shown below:
import java.util.*;
public class TestConcurrentList {
private static List common = new ArrayList();
private static class GenerateThread extends Thread {
private List common;
GenerateThread(List common) {
this.common = common;
}
@Override
public void run() {
while (true) {
common.add("foo");
if (common.size() > 1000) common.clear();
}
}
}
private static class ConsumeThread extends Thread {
private List common;
ConsumeThread(List common) {
this.common = common;
}
@Override
public void run() {
while (true) {
List priv = new ArrayList();
priv.addAll(common);
}
}
}
public static void main(String[] args) throws Exception {
Thread gen = new GenerateThread(common),
consume = new ConsumeThread(common);
gen.start();
consume.start();
System.out.println("Waiting...");
gen.join();
}
}
What makes this so hard debug is that (a) the exception doesn’t say anything about concurrency (it’s not like it throws an ConcurrentModificationException), (b) the exception actually occurs in the native Java libraries and (c) the source of the concurrent modifications may not be so obvious as in the reduced test case.
Conclusion? When possible, avoid concurrency or delegate it (to an RDBMS with proper transaction / locking support for example).
PS. This bug is not found by FindBugs (admittedly the support for checking concurrency bugs is fairly low at the moment) and is dependent on the version of the runtime. I reproduced it on 1.5.14, but not on 1.6.07.
Picture taken from yimhafiz’s photostream with permission.
]]>