Why doesn't thread wait for notify()? - java

Why doesn't thread wait for notify()? The thread starts and then goes to the waiting pool, but it proceeds to execute after that moment.
public class JavaApplication2 {
public static void main(String [] args) {
ThreadB b = new ThreadB();
synchronized(b) {
b.start();
try {
System.out.println("1");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
#Override
public void run() {
synchronized(this) {
total += 1;
//notify();
}
}
}

You are synchronizing on the thread object itself, which is wrong usage. What happens is that the dying thread-of-execution always calls notify on its Thread object: Thread.join relies on this. Therefore it is clear why you get the same behavior with and without your own notify in there.
Solution: use a separate object for thread coordination; this is the standard practice.

The method notifyAll() is invoked for the Thread object of the terminating thread. This fact is strangely documented in the description of the Thread.join, with the following sentence:
As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
Thus, if you don't explicitly read the description of join, which you don't necessarily have to, you don't get to know the reason for the strange behavior.

You cannot depend on not returning from wait until a notify: "interrupts and spurious wakeups are possible". In general, you should wrap a wait call in a loop while the thread should go on waiting.

If you try your code synchronizing on any object other that ThreadB you will find it never terminates. This is because there is a hidden call to notify.
Although I am not aware of anywhere that this is specified, Thread notifies itself when it ends. This is implicit in the way the join method is implemented. This is the code for join:
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
(From the JDK7 source code)
As you can see, the calls to wait only make sense if somewhere there is a call to notify that is called after the thread ends. The same call to notify is what allows your program to terminate.

You have nested synchronized {} constructs in the two places. These constructs seem doing something weird: the thread does not react into notify at all and only resumes when ThreadB (b) terminates. Remove this:
public class JavaApplication2 {
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();
try {
System.out.println(" ### Waiting for notify");
synchronized (b) {
b.wait();
}
System.out.println(" ### Notified");
} catch (InterruptedException e) {
}
System.out.println("### Total is: " + b.total);
}
}
class ThreadB extends Thread {
int total;
#Override
public void run() {
total += 1;
System.out.println(" *** Ready to notify in 5 secs");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println(" *** Notification sent");
synchronized (this) {
notify();
}
System.out.println(" *** 5 sec post notification");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println(" *** ThreadB exits");
}
}
The code above probably works correctly: with notify() present the main thread resumes after 5 seconds and before we see the message that ThreadB terminates. With notify() commented out the main thread resumes after 10 seconds and after the message about the termination of the ThreadB because notify() is called anywhay from the other code. Marko Topolnik explains why and from where this "behind the scene" notify() call comes from.

I was doing the same testing on the wait/notify opertaions while reading OCP SE 7, good catch. I think we should let the authoer to explain.

Related

why is java thread not timing out

I have a java thread implementation as follows:
class MyThread extends Thread {
private static Integer counter = 1;
public MyThread(final String name) {
super(name + "_" + counter);
counter++;
}
#Override
public void run() {
try {
sleep(0,2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName() + " true = " + true);
}
}
And the main class as follows:
public class ThreadingTest {
public static void main(String[] args) {
MyThread thisThread = new MyThread("MyThread");
thisThread.setDaemon(true);
thisThread.start();
try {
Thread.sleep(0,1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
However even though the thread is sleeping for 2 nanoseconds and the calling thread is sleeping only for 1 nano second, why is my SOUT printing the statement?
Considering the fact that timeout of the called thread is more than the calling thread, shouldn't the calling thread be terminated before it can print the statement?
Threads that are marked as daemon will be killed when all non daemon threads are finished. Therefor your thread is simply killed.
What is Daemon thread in Java?
You cannot have nanosecond precision with Thread.sleep(). Even executing those instructions will take more than a nanosecond. Try your code with miliseconds instead, and see if it works!
Method Thread.sleep determines only amount of time for which thread is sleeping (for how long thread is in the TIMED_WAITING state). After this time thread is removed from the set of waiting threads but still has to wait to obtain CPU time. And how long it will take is very nondeterministic parameter. You should never rely on time to determine exact sequence of threads execution.

Last thread is not executing

I am very new to multithreading, was trying a scenario in which a home has a mother(as producer),son,daughter and husband[As consumer] thread.I am trying to understand how wait and notify method can help here.
My classes are as below.
MotherAsProducer
package com.test.All.Threads;
public enum MotherAsProducer {
INSTANCE;
/*
*
*
* son Give request to prepare chapati to mother
* mother accepts it and start preparing , son/husband/daughter should wait by that time.
* mother notifies son/daughtor/husband that chapati is ready start consuming
* */
public synchronized void takeOrderAndMakeChapati(){
try {
System.out.println("Request got from "+Thread.currentThread().getName());
getStatusOfChapati();
wait();
System.out.println(Thread.currentThread().getName()+" ate chapati");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//lock re-entrance
public synchronized void getStatusOfChapati(){
try {
Thread.sleep(1200);
System.out.println("Chapati is prepared for "+Thread.currentThread().getName());
notifyAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static MotherAsProducer getMotherInstance(){
return MotherAsProducer.INSTANCE;
}
}
SonAsConsumer class
package com.test.All.Threads;
public class SonAsConsumer implements Runnable{
public void run(){
MotherAsProducer.getMotherInstance().takeOrderAndMakeChapati();
}
}
DaughterAsConsumer class
package com.test.All.Threads;
public class DaughterAsConsumer implements Runnable {
public void run(){
MotherAsProducer.getMotherInstance().takeOrderAndMakeChapati();
}
}
HusbandAsConsumer class
package com.test.All.Threads;
public class HusbandAsConsumer implements Runnable {
public void run(){
MotherAsProducer.getMotherInstance().takeOrderAndMakeChapati();
}
}
Home class
package com.test.All.Threads;
public class Home {
public static void main(String args[]){
SonAsConsumer sac = new SonAsConsumer();
DaughterAsConsumer dac = new DaughterAsConsumer();
HusbandAsConsumer hac = new HusbandAsConsumer();
Thread tsac = new Thread(sac);
tsac.setName("Son");
Thread tdac = new Thread(dac);
tdac.setName("Daughter");
Thread thac = new Thread(hac);
thac.setName("Husband");
tsac.start();
tdac.start();
thac.start();
}
}
My output is different, every time as expected by nature of thread but one of the individual either husband, daughtor or son is not getting complete.
one instance of my output is as below.
Order she got from Daughter
Chapati is prepared for Daughter
Order she got from Son
Chapati is prepared for Son
Order she got from Husband
Chapati is prepared for Husband
Son ate chapati
Daughter ate chapati
My understanding here is when son,daughter and husband will start executing one of them will hit the synchronized method and execute wait() and will hold the lock , from that synchronized method again another synchronized method is called which will contain notify and the lock will be released and another thread will try to get the lock from the blocked pool and will execute in the same manner . here two threads are behaving as expected but the last one is not.
Kindly help here.
Briefly looking, it looks like the last thread to get to the wait will never get notified. Sequencing your calls you have each thread getting a lock, notifying all waiting threads, and then waiting. So, the last thread that hits the wait will never have anyone to notify them that they need to exit.
That is, if Thread A gets the lock initially, then it will do a println and a sleep then a println, then notify all waiting threads (there are none), and then become a waiting thread.
Then, lets say Thread B gets the lock. It will do a println and a sleep, then it will notify all (which will "notify" Thread A), then it will wait.
Now, either Thread C or Thread A will get the lock. If Thread A gets it, it will simply fall through and complete with the "ate" message. Then, Thread C can get the lock and it will eventually notify, waking B which can eat once C "waits". Now, there is no thread left to notify so that C will complete.
This make sense? Did I misread anything?
To verify what I'm suggesting is wrong, simply add in more threads. You should always have the last one that prints "Chapati is prepared for ..." will never eat it.
Fundamentally, I think the confusion is that "Mother" is not actually doing any work. What you probably wanted is to have "Mother" be a thread that has its own work log. So, when one of the other threads gives her work, you set a variable then notify mother and wait as the sibling. The mother will then wake up and do the work and notify the current thread waiting.
See what I mean? Metaphorically, you have 4 people in this program. But, you only have 3 threads.
Change the method in the enum class MotherAsProducer as follows: The unnecessary wait() method caused the issue. Since the method is synchronized, all other threads will be blocked before entering into the method until getting a notification from lock holding thread.
public synchronized void takeOrderAndMakeChapati() {
System.out.println("Request got from " + Thread.currentThread().getName());
getStatusOfChapati();
// wait(); - THIS WAIT IS CAUSING THE PROBLEM
System.out.println(Thread.currentThread().getName() + " ate chapati");
}
Remove wait and notifyAll calls from both takeOrderAndMakeChapati and getStatusOfChapati. You will get the expected result.
As precisely mentioned by Josh, one of the threads (last one) is still waiting for some external notification, and there is nobody to notify. You code is still running in the background. Just call wait(5000) and you can see it happening.
Both methods takeOrderAndMakeChapati and getStatusOfChapati are synchronized, therefore synchronization is not the issue.
Generally threads wait for some external dependency or condition, where some other thread(s) notifies the waiting one, when that condition is fulfilled.
I also tried to understand wait and notify when I started with multithreading. But as soon as I learned to use a Semaphore, I never looked back. Hopefully, the example below will give you some insight into the benefits of using a Semaphore. There is also a lot more useful stuff in the java.util.concurrent package that can be of great help.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class EatChapati {
static int CHAPATI_PREPARE_TIME_MS = 100;
static long RUN_TIME_MS = 2000;
static long SHUTDOWN_TIME_MS = 500;
static int CHAPATI_CONSUMERS = 5;
static volatile boolean stop;
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < CHAPATI_CONSUMERS; i++) {
executor.execute(new ChapatiConsumer(i + 1));
}
try { Thread.sleep(RUN_TIME_MS); } catch (Exception ignored) {}
stop = true;
executor.shutdownNow();
try { executor.awaitTermination(SHUTDOWN_TIME_MS, TimeUnit.MILLISECONDS); } catch (Exception ignored) {}
}
// 1 producer making chapati's
// 'true' for a fair semaphore: longest waiting consumer gets served
static Semaphore chapatiTurn = new Semaphore(1, true);
static AtomicInteger chapatiCount = new AtomicInteger();
static int getChapati(int consumerNumber) {
int chapatiNumber = 0;
boolean haveTurn = false;
try {
chapatiTurn.acquire();
// start of 'synchronized' block
haveTurn = true;
Thread.sleep(CHAPATI_PREPARE_TIME_MS);
chapatiNumber = chapatiCount.incrementAndGet();
System.out.println("Chapati " + chapatiNumber + " prepared for consumer " + consumerNumber);
} catch (Exception e) {
// Triggered by executor.shutdownNow
stop = true;
} finally {
if (haveTurn) {
chapatiTurn.release();
// end of 'synchronized' block
}
}
return chapatiNumber;
}
static class ChapatiConsumer implements Runnable {
int number;
ChapatiConsumer(int number) {
this.number = number;
}
public void run() {
int chapatisConsumed = 0;
while (!stop) {
if (getChapati(number) > 0) {
chapatisConsumed++;
}
}
System.out.println("Consumer " + number + " stopped after consuming " + chapatisConsumed + " chapatis.");
}
}
}

Why this code never deadlocks when I run it?

I'm trying out deadlock concepts in Java Multithreading. I came across a code snippet which could possibly result in deadlock:
public class Deadlock {
double amount = 10.0;
public double deposit(double d) {
amount += d;
return amount;
}
public double withdraw(double d) {
amount -= d;
return amount;
}
public static void transfer(Deadlock from, Deadlock to,double d) {
synchronized(from) {
synchronized(to) {
from.withdraw(d);
try {
System.out.println(Thread.currentThread().getName());
Thread.sleep(5000);
}catch(Exception e){}
to.deposit(d);
System.out.println("Done");
}
}
}
public static void main(String[] args) {
final Deadlock a = new Deadlock();
final Deadlock b = new Deadlock();
Thread t1 = new Thread(new Runnable() {
public void run() {
transfer(a, b, 10.0);
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
public void run() {
transfer(b, a, 10.0);
}
});
t2.start();
}
}
Basically, the code tries to acquire locks on objects a and b at the same time. However, when I run it, the code always completes successfully. Why doesn't this deadlock?
In order for the deadlock to occur, you need to have something like the following scenario happen:
t1 acquires lock a
t2 acquires lock b
t1 attempts to acquire lock b
t2 attempts to acquire lock a
Can you force this? You can try by moving your sleep statement in between lock acquisitions, but this all has to happen within a window thats not really under your direct control.
Try this:
public static void transfer(DeadLock from, DeadLock to,double d) {
synchronized(from) {
try {
System.out.println(Thread.currentThread().getName() +" acquires lock " +from);
Thread.sleep(5000);
synchronized(to) {
System.out.println(Thread.currentThread().getName() +" acquires lock " +to);
from.withdraw(d);
to.deposit(d);
System.out.println("Done");
}
}catch(Exception e){}
}
}
And to confirm you're in a deadlock, send the SIGQUIT signal to your Java process - the JVM will report the threads in a deadlock
It's simply up to the Thread scheduler if one thread is able to reach both of these
synchronized(from) {
synchronized(to) {
before the other thread reaches the first. Add a big enough sleep between those
synchronized (from) {
try {
Thread.sleep(20L);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
synchronized (to) {
and you should experience deadlock.
First thread that reaches the method transfer will acquire the both the resources(to and from) so fast that that it might not be interleaved with the second thread. Having said that, this code is still prone to deadlock. The below code tries to acquire only first lock long enough to second thread getting scheduled to run:
public static void transfer(Deadlock from, Deadlock to, double d) throws InterruptedException {
synchronized (from) {
Thread.sleep(5000);
synchronized (to) {
from.withdraw(d);
System.out.println(Thread.currentThread().getName());
to.deposit(d);
System.out.println("Done");
}
}
}
sleeping a Thread does not release the locks it holds, while waiting releases the lock
T1 has the locks over both deadlock objects, even during sleeping and only when T1 exists the respective synchronized locks , t2 gets access to it.
So to bring in deadlock, you need to sleep between the sychronized statements.
Also alternatively you can try instead of Thread.sleep(5000); to.wait(5000);

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();

why thread.stop() doesn't work?

I just learned from sun's document that when i invoke thread.stop() method, the run() method will be terminated as the ThreadDeath error thrown out, and also release all the locks this thread holds, how to prove it?
I tried my test program, shown below:
public static void main(String[] args) {
final Object lock = new Object();
try {
Thread t = new Thread() {
public synchronized void run() {
try {
synchronized (lock) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++)
System.out.println("runing.." + i);
System.out
.println((System.currentTimeMillis() - start) / 1000);
}
} catch (Throwable ex) {
System.out.println("Caught in run: " + ex);
ex.printStackTrace();
}
}
};
t.start();
// Give t time to get going...
Thread.sleep(100);
t.stop(); // EXPECT COMPILER WARNING
} catch (Throwable t) {
System.out.println("Caught in main: " + t);
t.printStackTrace();
}
}
Only if i put an wait() in the run() method, then i can catch the ThreadDeath error, does anyone know the details of how jvm handle stop()?
public static void main(String[] args) {
final Object lock = new Object();
try {
Thread t = new Thread() {
public synchronized void run() {
try {
synchronized (lock) {
wait();
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++)
System.out.println("runing.." + i);
System.out
.println((System.currentTimeMillis() - start) / 1000);
}
} catch (Throwable ex) {
System.out.println("Caught in run: " + ex);
ex.printStackTrace();
}
}
};
t.start();
// Give t time to get going...
Thread.sleep(100);
t.stop(); // EXPECT COMPILER WARNING
} catch (Throwable t) {
System.out.println("Caught in main: " + t);
t.printStackTrace();
}
}
The simple answer is that the jvm has no reliable way to stop a thread. To stop or interrupt a thread, the target thread needs to cooperate by entering some interrupt-able state, such as sleep() or wait().
The Thread.stop() method has been deprecated for this reason (among others). See http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html for more details.
I do not think that I can explain better than Sun.
Here are the quotes from official Javadoc:
Deprecated. This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. If the target threalink textd waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait. For more information, see Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?.
See here:
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html
that is because the thread executes before your current thread comes out of sleep and calls the t.stop.
The Thread.stop() doesn't stop a thread. Instead it call Thread.stop(new ThreadDeath()) which triggers the thread to throw this Error, which is silently ignored by default. i.e. if you throw any other Throwable the uncaughtException will print it to System.err. From ThreadGroup
public void uncaughtException(Thread t, Throwable e) {
if (parent != null) {
parent.uncaughtException(t, e);
} else {
Thread.UncaughtExceptionHandler ueh =
Thread.getDefaultUncaughtExceptionHandler();
if (ueh != null) {
ueh.uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) {
System.err.print("Exception in thread \""
+ t.getName() + "\" ");
e.printStackTrace(System.err);
}
}
}
There is nothing else special/magical about this error. Your thread will unwind in the same manner at it would if you threw new ThreadDeath(). For comparison, try
thread.stop(new RuntimeException());
The explanations about Thread.stop are pretty much right on. The proper way to build a cooperative runnable is as follows:
public class MyRunnable implements Runnable {
private volatile boolean stopped = false;
public void stop() {
stopped = true;
}
public void run() {
// do stuff
if (stopped) {
// cleanup and return;
}
// do more stuff
if (stopped) {
// cleanup and return;
}
}
}
Runnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
r.stop();
t.join(); // if you want to wait for it to die.
OR
public class MyRunnable implements Runnable {
public void run() {
// do stuff
if (Thread.currentThread().isInterrupted()) {
// cleanup and return;
}
// do more stuff
if (Thread.currentThread().isInterrupted()) {
// cleanup and return;
}
}
}
Runnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
t.interrupt();
t.join(); // if you want to wait for it to die.
Note that in either case, you have strategic stop points in your code where you're checking to see if you should continue processing. The second approach has the advantage that interrupt aware operations like Thread.sleep and java.nio based I/O operations can be immediately interrupted and don't have to wait for your stop point. Instead they would throw an InterruptedException immediately (or in the case of NIO a ClosedByInterruptException). Note that standard java.io based I/O is not interrupt aware, and you'll have to wait for one of your coded stop points.
The real answer is that the stop method of class Thread calls the private stop1 method which is synchronized. As your implementation of the thread's run method is also synchronized the stop1 method cannot be entered until the run method is exited.

Categories