Check if external service is running - java

I have to check if an external service is up and running or is hung. If the external process is hung, I have to kill it and restart it.
PROBLEM STATEMENT:
To check if the process is hung, I try to invoke it. If it is hung, I wont get any response and I would know that the service is hung.
The problem is when I try to invoke the process, and if it is struck, even the java thread would be hung, So I thought I could create a thread and invoke the process in that thread.
I will have a counter in parent thread and if the child thread does not return in some time, I would kill (call inturrupt()) on it.
But even, the parent thread hangs here.
I have a Class MyThreadHandler as follows:
public class MyThreadHandler {
/**
* #param args
*/
public static void main(String[] args) {
MyThreadHandler myThreadHandler = new MyThreadHandler();
myThreadHandler.handleThread();
}
public void handleThread() {
System.out.println("STARTING LOOPER THREAD");
boolean isRunning = false;
int counter = 0;
MyThreaad myThread = new MyThreaad();
if (!isRunning) {
myThread.start();
System.out.println("aaaaaaaaaaaaaaaa");
isRunning = true;
}
while (true) {
System.out.println("while loop");
counter++;
if (!myThread.isAlive() || counter == 1000) {
System.out.println("HUNG THREAD::: Killing thread");
myThread.interrupt();
break;
}
}
}
}
My Thread class is as follows:
public class MyThreaad extends Thread{
public void run() {
System.out.println("STARTING LOOPER THREAD");
MyLooper myLooper = new MyLooper();
myLooper.loopIndefinite();
};
}
And MyLooper:
public class MyLooper {
public void loopIndefinite() {
while (true){
System.out.println("a");
}
}
}

I suspect the problem is that both loops stay busy. In this situation, the thread scheduler may execute one loop for a long time, and the other (parent) appears hung.
The MyLooper loop can not be changed, I guess, because it simulates the hung process. The following could be done to make sure the parent thread gets some execution time:
public void handleThread() {
System.out.println("STARTING LOOPER THREAD");
boolean isRunning = false;
int counter = 0;
MyThreaad myThread = new MyThreaad();
myThread.setPriority(Thread.MIN_PRIORITY); // <=== set priority
if (!isRunning) {
myThread.start();
System.out.println("aaaaaaaaaaaaaaaa");
isRunning = true;
}
while (true) {
try {
Thread.sleep(100); // <=== sleep
} catch(InterruptedException e) {
}
System.out.println("while loop");
counter++;
if (!myThread.isAlive() || counter == 1000) {
System.out.println("HUNG THREAD::: Killing thread");
myThread.interrupt();
break;
}
}
}
I added 2 lines, one to set the thread priority of the "hanging thread" to a low value, such that the parent thread gets execution time even when the thread is busy. The second line is a sleep, this makes sure the parent thread doesn't take all the available execution time.

If you don't check for the interrupted state there's no chance that myThread.interrupt() will do what you want.
you have to add the following in the loopIndefinite method:
if(Thread.interrupted()) throw new InterruptedException();
Your loops are very aggressive for the CPU, you should not stress CPU like that. It's better to use ExecutorServices and Future as suggested by Fildor.

Related

How to Start Pause and Stop thread in Java in proper way

I started "play" with Threads in Java
and wondering about my solution with starting pausing and stopping thread...
Start and Pause works everytime (i think) fine, but when i do Stop method i get Exception:
java.lang.InterruptedException: sleep interrupted
but is stopped after that (i think so)
this is my super simple code :)
code snippet with buttons:
var ref = new Object() {
Thread th = new Thread(main);
};
startItem.addActionListener(e -> {
if (ref.th.getState() == Thread.State.NEW)
ref.th.start();
else
main.setPaused(false);
});
pauseItem.addActionListener(e -> {
if (ref.th.getState() == Thread.State.TIMED_WAITING)
main.setPaused(true);
});
stopItem.addActionListener(e -> {
main.setRunning(false);
ref.th.interrupt();
ref.th = new Thread(main);
});
and here my Runnable class:
public class MyRunnable implements Runnable {
private volatile boolean running;
private volatile boolean paused;
#Override
public void run() {
Logger.info("MONITORING STARTED");
running = true;
paused = false;
int counter = 0;
while (running) {
if (!paused) {
sleep();
System.out.println("thread working: " + counter);
counter++;
}
}
}
public void setRunning(boolean running) {
if(!running)
Logger.info("MONITORING STOPPED");
this.running = running;
}
public void setPaused(boolean paused) {
if(paused)
Logger.info("APPLICATION PAUSED = TRUE (paused)");
else
Logger.info("APPLICATION PAUSED = FALSE (continues to work...)");
this.paused = paused;
}
private void sleep() {
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Am I doing it correctly?
Or is this a stupid approach and should I do it differently to make it correct?
Whenever I "sweat out" some code, I wonder if I'm doing it in a nice and correct way... it's rather a sign of a lack of skills and professionalism :(
Thank you in advance for your help and patience and sorry for my english. :) Regards.
Your thread is printing the error message because you wrote ex.printStackTrace(). That's what printStackTrace() is for: You use it to call attention to an unexpected exception.
But if your other thread calls ref.th.interrupt(), then is the exception really unexpected? There's no rule that says you must call printStackTrace() every time your code handles an exception. It looks like you're already using Log4J, so one option would be to call Logger.info("interrupted", ex). Another option would be to simply do nothing at all in the handler, because after the handler is finished, the thread eventually* will check the running flag.
* Personally, I would move the sleep() call to the bottom of the loop because that way, if the sleep() is interrupted, it won't print "working" or increment the counter again until the thread is un-paused.
while (running) {
if (!paused) {
System.out.println("thread working: " + counter);
counter++;
sleep();
}
}
Better still: Move the sleep() out of the if statement, so that the thread will not consume 100% CPU time (as mentioned in a comment by #MadProgrammer) while it is "paused."
while (running) {
if (!paused) {
System.out.println("thread working: " + counter);
counter++;
}
sleep();
}

handle multiple infinite tasks in a single thread? P.S run one task at a time and control its task behavior(i.e starting/stoping task) from outside

I want to make a single thread which would contain 3 infinite tasks.
I want one task to run at a time and start/stop running task when required.
For example first I want task 1 to run, then I want task 2 to run but after stopping task 1 and again I want task 1 to run but after stopping of task 2 and so on.
Infinite task needs to check some condition and if that condition is satisfied perform some operations and if not satisfied sleep for few seconds and after wake up perform the above same operations again.
Infinite Runnable task looks some thing like this:
new Runnable(){
while(1){
if(TaskQueue.getInstance().size()<= 100){
TaskQueue.getInstance().push("add command to the end of queue");
}else{
try {
Thread.sleep(10000);
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Any help would be appreciated?
Edit : I modified my question. I want a continuous single running thread(some thing like looper ) to monitor 3 infinite tasks and control this single continuous running thread tasks from outside.
Use this for start/stop thread in real-time:
class MyThread extends Thread {
private volatile boolean running = true; // Run unless told to pause
...
#Override
public void run() {
// Only keep painting while "running" is true
// This is a crude implementation of pausing the thread
while (true) {
if (Thread.currentThread().isInterrupted()) {
return;
}
if (running) {
//Your code
} else yield;
}
}
public void pauseThread() throws InterruptedException {
running = false;
}
public void resumeThread() {
running = true;
}
}
For pause thread use this:
myThread.pauseThread();
For resume thread use this:
myThread.resumeThread();
For stop thread use this (Not recommended):
myThread.stop();
For currently stop thread use this:
myThread.interrupt();
You must use a class like Thread that already implements Runnable.
new Thread(){....};
And the way it works it's:
Thread t = new Thread(){.....};
t.start();
t.stop();
You could also initialize a new thread, like:
Thread exampleThread = new thread();
After this you can start it at any point in your code by:
exampleThread.start();
you can use Semaphore,
to Manage the amount of signal.
private final static Semaphore semaphore = new Semaphore(0);
public static void main(String[] args) throws Exception {
//入口
threadTest();
}
public static void thread1() {
try{
//…… some code
}
finally{
semaphore.release();
}
}
public static void thread2() {
semaphore.acquire(1);
}
The question is my first answer,thanks.
I finally made my task scheduler. The API of which looks something like this:
TaskScheduler taskScheduler = TaskScheduler.getInstance();
taskScheduler.startTaskOne();
taskScheduler.stopTaskOne();
taskScheduler.startTaskTwo();
taskScheduler.stopTaskTwo();
Runs one task at a time (because I used Executors.newSingleThreadExecutor()).
We can control the execution of the task from outside:
public class TaskScheduler {
private static ExecutorService mTaskRunningService;
private static TaskScheduler mInstance;
private Future mFirstTaskFuture = null;
private Future mSecondTaskFuture = null;
static {
configure();
}
private static void configure() {
mTaskRunningService = Executors.newSingleThreadExecutor();
}
public static TaskScheduler getInstance() {
if (mInstance == null) {
mInstance = new TaskScheduler();
}
return mInstance;
}
private Runnable mTaskOneRunnable = new Runnable() {
#Override
public void run() {
try {
while (true) {
/** stop this single thread (i.e executing one task at time) service if this thread is interrupted
* from outside because documentation of {#link java.util.concurrent.ThreadPoolExecutor#shutdownNow()}
* says we need to do this*/
if (Thread.currentThread().isInterrupted()) {
return;
}
// task one work.......
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
private Runnable mTaskTwoRunnable = new Runnable() {
#Override
public void run() {
try {
while (true) {
/** stop this single thread (i.e executing one task at time) service if this thread is interrupted
* from outside because documentation of {#link java.util.concurrent.ThreadPoolExecutor#shutdownNow()}
* says we need to do this*/
if (Thread.currentThread().isInterrupted()) {
return;
}
// task two work......
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
public synchronized void startTaskOne() {
if (mFirstTaskFuture == null) {
// start executing runnable
mFirstTaskFuture = mTaskRunningService.submit(mTaskOneRunnable);
}
}
public synchronized boolean stopTaskOne() {
if (mFirstTaskFuture != null) {
// stop general reading thread
mFirstTaskFuture.cancel(true);
// cancel status
boolean status = mFirstTaskFuture.isDone();
// assign null because startTaskOne() again be called
mGeneralFuture = null;
return status;
}
return true;
}
public synchronized void startTaskTwo() {
if (mSecondTaskFuture == null) {
// start executing runnable
mSecondTaskFuture = mTaskRunningService.submit(mTaskTwoRunnable);
}
}
public synchronized boolean stopTaskTwo() {
if (mSecondTaskFuture != null) {
// clear task queue
mTaskQueue.clearTaskQueue();
// stop 22 probes reading thread
mSecondTaskFuture.cancel(true);
// cancel status
boolean status = mSecondTaskFuture.isDone();
// assign null because startTaskTwo() again be called
mSecondTaskFuture = null;
return status;
}
return true;
}
}

Java Multithreading doesn't seem to be correctly working

I have a class which processes something. I'm trying to run a number of instances of this class in parallel.
However, I'm not sure if in TaskManager.startAll(), when I call r.go(), whether this would cause r to start running in its own thread, or within the main thread?
The total execution time that I'm getting seems to be very high, and despite my attempts at optimizing, nothing seems to be having any effect. Also, if I run a profiler on my project in Netbeans, it shows all the threads as sleeping. So I'd like to know if I'm doing something wrong?
This is the structure of the class:
public class TaskRunner implements Runnable {
private boolean isRunning = false;
public void run() {
while(true) {
while (! running) {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
process();
}
}
public void go() {
isRunning = true;
}
public void stop() {
isRunning = false;
}
private void process() {
//Do some number crunching and processing here
}
}
Here's how these are being run / managed:
public class TaskManager {
private ArrayList<TaskRunner> runners = new ArrayList<>();
public TaskManager() {
for (int i = 0; i < 10; i++) {
TaskRunner r = new TaskRunner();
new Thread(r).start();
runners.add(r);
}
}
public void startAll() {
for (TaskRunner r : runners) {
r.go();
}
}
}
Indeed, you are not "doing it right." If you want to create a multi-threaded Java application, the place to start is with the java.util.concurrent package.
It appears from your code that you want to run ten tasks in parallel. I assume that after "number crunching and processing," you'll want to aggregate the results and do something with them in the main thread. For this, the invokeAll() method of ExecutorService works well.
First, implement Callable to do the work you show in your process() method.
final class YourTask implements Callable<YourResults> {
private final YourInput input;
YourTask(YourInput input) {
this.input = input;
}
#Override
public YourResults call()
throws Exception
{
/* Do some number crunching and processing here. */
return new YourResults(...);
}
}
Then create your tasks and run them. This would take the place of your main() method:
Collection<Callable<YourResults>> tasks = new List<>(inputs.size());
for (YourInput i : inputs)
tasks.add(new YourTask(i));
ExecutorService workers = Executors.newFixedThreadPool(10);
/* The next call blocks while the worker threads complete all tasks. */
List<Future<YourResult>> results = workers.invokeAll(tasks);
workers.shutdown();
for (Future<YourResult> f : results) {
YourResult r = f.get();
/* Do whatever it is you do with the results. */
...
}
However, I'm not sure if in TaskManager.startAll(), when I call r.go(), whether this would cause r to start running in its own thread, or within the main thread?
So my first comment is that you should make isRunning be volatile since it is being shared between threads. If the threads are not starting when it goes to true (or seem to be delayed in starting) then I suspect that's your problem. volatile provides memory synchronization between the threads so the thread that calls go() and makes a change to isRunning will be seen immediately by the thread waiting for the change.
Instead of spinning like this, I would use wait/notify:
// this synchronizes on the instance of `TaskRunner`
synchronized (this) {
// always do your wait in a while loop to protect against spurious wakeups
while (!isRunning && !Thread.currentThread().isInterrupted()) {
try {
// wait until the notify is called on this object
this.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
Then in the go() method you should do the following. stop() would be similar.
public void go() {
synchronized (this) {
isRunning = true;
this.notifyAll();
}
}
Notice that you should handle thread interrupts carefully. Test for isInterrupted() in the while running loop and re-interrupt a thread when InterruptedException is thrown is always a good pattern.
The total execution time that I'm getting seems to be very high, and despite my attempts at optimizing, nothing seems to be having any effect. Also, if I run a profiler on my project in Netbeans, it shows all the threads as sleeping.
So although the threads are mostly sleeping, they are still each looping 1000 times a second because of your Thread.sleep(1). If you increased the time sleeping (after making isRunning be volatile) they would loop less but the right mechanism is to use the wait/notify to signal the thread.
Awful solution, terrible. first I highly recommend you start reading some tutorial like [this]
Second, if threads should wait for a signal to go for some job, so why just don't you wait them!!!!!, something like this
import java.util.ArrayList;
public class TaskManager
{
//////////////////////
public volatile static Signal wait=new Signal();
//////////////////////
private ArrayList<TaskRunner> runners = new ArrayList<>();
public TaskManager()
{
for (int i = 0; i < 10; i++)
{
TaskRunner r = new TaskRunner();
new Thread(r).start();
runners.add(r);
}
try {
Thread.sleep(1000);
startAll();
Thread.sleep(1000);
pauseAll();
Thread.sleep(1000);
startAll();
Thread.sleep(1000);
haltAll();System.out.println("DONE!");
}catch(Exception ex){}
}
public void startAll()
{
synchronized(wait){
wait.setRun(true);;
wait.notifyAll();
}
}
public void pauseAll(){
wait.setRun(false);
}
public void haltAll(){
for(TaskRunner tx:runners){tx.halt();}
}
public static void main(String[] args) {
new TaskManager();
}
}
class TaskRunner implements Runnable
{
private Thread thisThread;
private volatile boolean run=true;
public void run()
{
thisThread=Thread.currentThread();
while(run){
if(!TaskManager.wait.isRun()){
synchronized(TaskManager.wait)
{
if(!TaskManager.wait.isRun()){
System.out.println("Wait!...");
try
{
TaskManager.wait.wait();
}
catch (Exception e)
{
e.printStackTrace();
break;
}
}
}}
process();
}
}
private double r=Math.random();
private void process(){System.out.println(r);try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}}
public void halt(){run=false;thisThread.interrupt();}
}
class Signal{
private boolean run=false;
public boolean isRun() {
return run;
}
public void setRun(boolean run) {
this.run = run;
}
}
in above sample, all runners works till the Signal run boolean is true, and simple TaskManager class set tit as false for every time it needs to pause the threads. and about the halt, it just set the shutdown(run) flag to false, and also interrupt the thread because of if thread is in wait state.
I hope I could prove your solution is like dream-on story, and also could explained enough about my solution.
have a good parallel application :)

Gracefully shutdown a program with multiple threads having infinite while loop

I have a program which creates 10 threads, and each thread has an infinitely running while loop.
I need help to efficiently implement a Shutdown hook which can effectively STOP all the threads. Since I want to do a graceful shutdown each Thread should finish as soon as it finds the stop flag turned to TRUE.
public class SampleGSH implements Runnable{
private static boolean stop = false;
public static void main(String[] args) {
for(int i = 0; i < 10;i++) {
Thread t = new Thread(new SampleGSH(), "name"+i);
t.start();
}
}
#Override
public void run() {
Runtime.getRuntime().addShutdownHook(new Thread("shutdown thread") {
public void run()
{
System.out.println("*******");
synchronized (this)
{
System.out.println("Turning switch off");
stop = true;
}
}
});
synchronized (this) {
while(!stop)
{
//Some logic which should not be killed abruptly once it starts running, a graceful shut down will not allow this code to start
}
}
}
}
Any help will be truly appreciated.
I need help to efficiently implement a Shutdown hook which can effectively STOP all the threads.
If you have any fields that are shared between multiple threads, they need to be synchronized. In this case your stop should be volatile. Without this, there is nothing that ensures that the threads will see the value of stop change to true. See this tutorial for information about atomic access.
See: Using boolean var for stopping threads
Couple other comments:
If you are starting a number of threads, you should consider using an ExecutorService
Your while loop is inside of a synchronized block. This does nothing and the stop field will not get memory synchronized since it gets updated externally while inside of the block.
Another way to stop a thread would be to interrupt() it. See this tutorial.
while (!thread.currentThread().isInterrupted()) {
...
}
...
t.interrupt();
Instead of a single static stop boolean, you could give every thread its own stop boolean. Then store all thread objects when creating them and set their stop boolean to true in the shutdown hook thread (which would be hooked in the main method).
Something like this:
import java.util.ArrayList;
import java.util.List;
public class SampleGSH extends Thread {
public boolean stop = false;
private static List<SampleGSH> threads = null;
public static void main(String[] args) {
threads = new ArrayList<SampleGSH>();
int numThreads = 10;
for (int i = 0; i < numThreads; i++) {
SampleGSH t = new SampleGSH();
threads.add(t);
t.start();
}
Runtime.getRuntime().addShutdownHook(new Thread("shutdown thread") {
public void run() {
System.out.println("*******");
for (SampleGSH t : threads) {
t.stop = true;
}
}
});
}
#Override
public void run() {
{
while (!stop) {
// Some logic which should not be killed abruptly once it starts
// running, a graceful shut down will not allow this code to
// start
}
}
}
}
Forget that addShutdownHook guff ... keep it simple ...
Make the static stop variable volatile ...
then add this method to SampleGSH ...
public void shutdown() {
stop = true;
}
then call it when you want to stop the threads!

Getting a thread to pause - Thread.wait()/Thread.notify()

I'm trying to understand how threads work, and I wrote a simple example where I want to create and start a new thread, the thread, display the numbers from 1 to 1000 in the main thread, resume the secondary thread, and display the numbers from 1 to 1000 in the secondary thread. When I leave out the Thread.wait()/Thread.notify() it behaves as expected, both threads display a few numbers at a time. When I add those functions in, for some reason the main thread's numbers are printed second instead of first. What am I doing wrong?
public class Main {
public class ExampleThread extends Thread {
public ExampleThread() {
System.out.println("ExampleThread's name is: " + this.getName());
}
#Override
public void run() {
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
}
}
public static void main(String[] args) {
new Main().go();
}
public void go() {
Thread t = new ExampleThread();
t.start();
synchronized(t) {
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
synchronized(t) {
t.notify();
}
}
}
You misunderstand how wait/notify works. wait does not block the thread on which it is called; it blocks the current thread until notify is called on the same object (so if you have threads A and B and, while in thread A, called B.wait(), this will stop thread A and not thread B - for as long as B.notify() is not called).
So, in your specific example, if you want main thread to execute first, you need to put wait() inside the secondary thread. Like this:
public class Main {
public class ExampleThread extends Thread {
public ExampleThread() {
System.out.println("ExampleThread's name is: " + this.getName());
}
#Override
public void run() {
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
}
}
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
}
}
public static void main(String[] args) {
new Main().go();
}
public void go() {
Thread t = new ExampleThread();
t.start();
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
synchronized(t) {
t.notify();
}
}
}
However, even this code may not work like you want. In a scenario where the main thread gets to the notify() part before the secondary thread had a chance to get to the wait() part (unlikely in your case, but still possible - you can observe it if you put Thread.sleep at the beginning of the secondary thread), the secondary thread will never be waken up. Therefore, the safest method would be something similar to this:
public class Main {
public class ExampleThread extends Thread {
public ExampleThread() {
System.out.println("ExampleThread's name is: " + this.getName());
}
#Override
public void run() {
synchronized (this) {
try {
notify();
wait();
} catch (InterruptedException e) {
}
}
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
}
}
public static void main(String[] args) {
new Main().go();
}
public void go() {
Thread t = new ExampleThread();
synchronized (t) {
t.start();
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int i = 1; i < 1000; i++) {
System.out.println(Thread.currentThread().getName());
System.out.println(i);
}
synchronized(t) {
t.notify();
}
}
}
In this example the output is completely deterministic. Here's what happens:
Main thread creates a new t object.
Main thread gets a lock on the t monitor.
Main thread starts the t thread.
(these can happen in any order)
Secondary thread starts, but since main thread still owns the t monitor, the secondary thread cannot proceed and must wait (because its first statement is synchronized (this), not because it happens to be the t object - all the locks, notifies and waits could as well be done on an object completely unrelated to any of the 2 threads with the same result.
Primary thread continues, gets to the t.wait() part and suspends its execution, releasing the t monitor that it synchronized on.
Secondary thread gains ownership of t monitor.
Secondary thread calls t.notify(), waking the main thread. The main thread cannot continue just yet though, since the secondary thread still holds ownership of the t monitor.
Secondary thread calls t.wait(), suspends its execution and releases the t monitor.
Primary thread can finally continue, since the t monitor is now available.
Primary thread gains ownership of the t monitor but releases it right away.
Primary thread does its number counting thing.
Primary thread again gains ownership of the t monitor.
Primary thread calls t.notify(), waking the secondary thread. The secondary thread cannot continue just yet, because the primary thread still holds the t monitor.
Primary thread releases the t monitor and terminates.
Secondary thread gains ownership of the t monitor, but releases it right away.
Secondary thread does its number counting thing and then terminates.
The entire application terminates.
As you can see, even in such a deceptively simple scenario there is a lot going on.
You are lucky that your program terminates at all.
When you call t.wait() your main threads stops and waits indefinitely on a notification.
It never gets it, but I believe is awaken by spurious wakeup when the secondary thread finishes. (Read here on what a spurious wakeup is).
ExampleThread doesn't wait() or notify(), and isn't synchronized on anything. So it will run whenever it can without any coordination with other threads.
The main thread is waiting for a notification which never comes (this notification should be sent by another thread). My guess is that when the ExampleThread dies, the main thread is woken "spuriously," and completes.
The thread that should wait for another to complete must perform the call to wait() inside a loop that checks for a condition:
class ExampleThread extends Thread {
private boolean ready = false;
synchronized void ready() {
ready = true;
notifyAll();
}
#Override
public void run() {
/* Wait to for readiness to be signaled. */
synchronized (this) {
while (!ready)
try {
wait();
} catch(InterruptedException ex) {
ex.printStackTrace();
return; /* Interruption means abort. */
}
}
/* Now do your work. */
...
Then in your main thread:
ExampleThread t = new ExampleThread();
t.start();
/* Do your work. */
...
/* Then signal the other thread. */
t.ready();

Categories