user1255246
user1255246

Reputation: 109

java producer-consumer multithreading benchmark. Why does it stop?

Please, help me with my problem.

I have java program - test for server, something like echo, a benchmark tool.

To simplify:

I send to server 100 messages from a different number of threads (simulate real-world producers, for example, from 10 clients or 1, doesn't really matter) and receive responses.

I have the same situation with consumers (comsumer=thread). Producers and consumers generate events (message received from... message sent from... etc.)

My main implements MyEvenListener, with onMessage() and counts everything up.

My problem is that I can not receive all 100 messages back and count them, because the program stops after messages are sent. I know that this is something simple, but can't figure out how to fix it. :(

here's my code:

public static void main(String[] args) throws InterruptedException {
    Main m = new Main();
    m.init();
}
private int mesReceved=0;
public void init() throws InterruptedException {
    Sender s = new Sender(15,this);
    Resender r = new Resender(15,this);
    r.createThreads();
    r.startThreads();
    s.createThreads();
    s.startThreads();
    System.out.println(mesReceved);

}
public void onEvent(String string) {
    mesReceved++;
}

Upvotes: 1

Views: 475

Answers (4)

maasg
maasg

Reputation: 37435

Your problem lies in the fact the the main thread terminates after the setup process and therefore terminates all other threads.

An elegant way to wait for threads to finish their work is to use a high-level synchronization aid, like CountDownLatch.

In this case, you could rewrite your init code like this:

public void init() throws InterruptedException {
    ...
    producer = r.createThreads();
    r.startThreads();
    consumer = s.createThreads();
    s.startThreads();
    ...
    producer.getCountDownLatch().await();      // wait for all producers to finish
    consumer.getCountDownLatch().await();      // wait for all consumers to finish 
    // note: you could also encapsulate the latch and internally delegate the await
    // producer.await(); // nicer to read
}

On your Sender and Receiver classes, you create and maintain the CountDownLatch:

class Sender {
    final CountDownLatch sync;
    public Sender (int threadCount) {
        sync = new CountDownLatch(threadCount);
        ...
    }
    public CountDownLatch getCountDownLatch() {
        return sync;
    }
    // alternative
    public boolean await() {
        return sync.await();
    }
} 

When you create the threads, you pass the countDownLatch to each runnable. When they are done working, you decrement the latch:

class MyRunnable implements Runnable {
    private final CountDownLatch latch;
    public MyRunnable(CountDownLatch latch) {
        this.latch = latch;
        ...
    } 
    public void run() {
        // DO STUFF
        latch.countDown();
    }
}

With this synchronization process in place, your program will only terminate when all producers and consumers have done their job. Additionally. the await method can take a timeout as argument, sothat you can ensure program termination within some boundaries. e.g. let all producers work, but wait only 5 minutes for the consumers:

public void init() {
    ...
    producer.getCountDownLatch().await();      // wait for all producers to finish
    boolean allFinished = consumer.getCountDownLatch().await(5, TimeUnit.MINUTES);      // wait 5 minutes for all consumers to finish.
    if (!allFinished) {
        // alert that not all consumers ended on time
    }
    ...
}

Upvotes: -1

Tudor
Tudor

Reputation: 62439

Are you actually waiting for the threads to finish before leaving main? You should use Thread.join on all the created threads at the end of main, otherwise the main thread will just exit without waiting for the children to finish.

Upvotes: 1

xuincherguixe
xuincherguixe

Reputation: 101

How are you launching your program? It could be completing successfully and then closing the window. There's a few ways around that.

One thought that comes to mind is that you could try a Thread.sleep(time) in your main. (Where time is how long you want it to wait in milliseconds. )

Upvotes: 0

Peter Lawrey
Peter Lawrey

Reputation: 533530

I don't see a problem in this code.

Can you try simplifying the problem e.g. less threads until the problem stops occurring.

In the simplest case e.g. with 4 threads, where this happens

  • take a thread stack,
  • use debugging or
  • add logging to diagnose the problem.

Upvotes: 1

Related Questions