views:

507

answers:

3

How do threads that rely on one another communicate in Java?

For example, I am building a web crawler with threads that need data that comes from other threads.

+4  A: 

That depends on the nature of the communication.

  • Is it duplex (ie A talks to B and B talks to A)?
  • Is it communication of data or communication of completion?
  • and so on.

The simplest and most advisable form of inter-thread communication is simply to wait for the completion of other threads. That's most easily done by using Futures:

ExecutorService exec = Executors.newFixedThreadPool(50);
final Future f = exec.submit(task1);
exec.submit(new Runnable() {
  @Override
  public void run() {
    f.get();
    // do stuff
  }
});

The second task won't execute until the first completes.

Java 5+ has many concurrent utilities for dealing with this kind of thing. This could mean using LinkedBlockingQueues, CountDownLatch or many, many others.

For an in-depth examination of concurrency Java Concurrency in Practice is a must-read.

cletus
The threads don't go both ways, one thread waits for the result of another but not vice versa. Admittedly I'm a bit intimidated by the use of ExecutorService and Future, as I've never heard of them before. Is there another method of interthread communication not using Future and ExecutorService?
tipu
There's no need to be intimidated by `ExecutorService` and `Future`. They are reasonably simple and should take less than 2 hours to learn. Using `Future`s is easier than the standard queue classes, and a lot easier than rolling your own queue classes using `wait()` and `notify()`.
finnw
@cletus, -1 for calling `Future.get()` from within a task in a *fixed* thread pool. The danger there should be obvious.
finnw
@finnw: of course theres a danger but in the absence of the requirements for the communication or a better description you can't possibly suggest a method without danger.
cletus
This particular danger can be rectified by using a cached thread pool.
finnw
@finnw: and a cached thread pool can create other problems. That's kinda the point.
cletus
Please give an example. Here's a description of the kind of problem I was referring to: http://weblogs.java.net/blog/2008/11/25/tricks-and-tips-aio-part-1-frightening-thread-pool
finnw
@finnw: cached thread aren't limited. I've had a system fail because it created 30K+ threads because of this. On the same system, capping it to 2,000 threads not only worked but had significantly more overall throughput than the times the system didn't fall over with a cached thread pool. My point is that blanket statements like stating Future.get() in a fixed thread pool is dangerous in a vague question is naive and simply can't be made with any certainty.
cletus
A: 

Take a look at java.util.Observer/java.util.Observable. They are exactly what you are looking for.

David Sowsy
A: 

You could use 2 ExecutorServices, submit a Callable implementation to service A that knows about follow on service B. When the Callable has completed it's work, it submits a new task to service B that does something additional with the results.

You could use a CountDownLatch or some other barrier if you need to perform additional work once all items have been processed in both services.

The ExecutorService api is pretty straight forward, for the most part you'll probably be using something like .newFixedThreadPool(int threads) and submitting Runnables/Callables to it.

Chris