Reputation: 109
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
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
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
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
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
Upvotes: 1