Title says it all. I have some code which is included below and I am wondering how I would go about obtaining the statistics/information related to the threads (i.e. how many different threads are running, names of the different threads). For consistency sake, image the code is run using 22 33 44 55 as command line arguments.
I am also wondering what the purpose of the try blocks are in this particular example. I understand what try blocks do in general, but specifically what do the try blocks do for the threads.
public class SimpleThreads {
//Display a message, preceded by the name of the current thread
static void threadMessage(String message) {
long threadName = Thread.currentThread().getId();
System.out.format("id is %d: %s%n", threadName, message);
}
private static class MessageLoop implements Runnable {
String info[];
MessageLoop(String x[]) {
info = x;
}
public void run() {
try {
for (int i = 1; i < info.length; i++) {
//Pause for 4 seconds
Thread.sleep(4000);
//Print a message
threadMessage(info[i]);
}
} catch (InterruptedException e) {
threadMessage("I wasn't done!");
}
}
}
public static void main(String args[])throws InterruptedException {
//Delay, in milliseconds before we interrupt MessageLoop
//thread (default one minute).
long extent = 1000 * 60;//one minute
String[] nargs = {"33","ONE", "TWO"};
if (args.length != 0) nargs = args;
else System.out.println("assumed: java SimpleThreads 33 ONE TWO");
try {
extent = Long.parseLong(nargs[0]) * 1000;
} catch (NumberFormatException e) {
System.err.println("First Argument must be an integer.");
System.exit(1);
}
threadMessage("Starting MessageLoop thread");
long startTime = System.currentTimeMillis();
Thread t = new Thread(new MessageLoop(nargs));
t.start();
threadMessage("Waiting for MessageLoop thread to finish");
//loop until MessageLoop thread exits
int seconds = 0;
while (t.isAlive()) {
threadMessage("Seconds: " + seconds++);
//Wait maximum of 1 second for MessageLoop thread to
//finish.
t.join(1000);
if (((System.currentTimeMillis() - startTime) > extent) &&
t.isAlive()) {
threadMessage("Tired of waiting!");
t.interrupt();
//Shouldn't be long now -- wait indefinitely
t.join();
}
}
threadMessage("All done!");
}
}
you can use VisualVM for threads monitoring. which is included in JDK 6 update 7 and later. You can find visualVm in JDK path/bin folder.
VisualVM presents data for local and remote applications in a tab
specific for that application. Application tabs are displayed in the
main window to the right of the Applications window. You can have
multiple application tabs open at one time. Each application tab
contains sub-tabs that display different types of information about
the application.VisualVM displays real-time, high-level data on
thread activity in the Threads tab.
For the first issue:
Consider using VisualVM to monitor those threads. Or just use your IDEs debugger(eclipse has such a function imo).
I am also wondering what the purpose of the try blocks are in this particular example.
InterruptedExceptions occur if Thread.interrupt() is called, while a thread was sleeping. Then the Thread.sleep() is interrupted and the Thread will jump into the catch-code.
In your example your thread sleeps for 4 seconds. If another thread invokes Thread.interrupt() on your sleeping one, it will then execute threadMessage("I wasn't done!");.
Well.. as you might have understood now, the catch-blocks handle the sleep()-method, not a exception thrown by a thread. It throws a checked exception which you are forced to catch.
If you are not able to use tools like VisualVM (which is very useful, IMHO), you can also dump the thread stack in Java, e.g. to your logfile. I am using such dumps on my server programs, when certain thresholds are crossed. I found doing such snapshots as part of the program very helpful. Gives you some hints on what happened before the system crashes and it is too late to use profilers (deadlock, OutOfMemory, slowdown etc.). Have a look here for the code: Trigger complete stack dump programmatically?
Related
I'm investigating a high CPU usage issue we're experiencing with a Glassfish 3.1.2.2 hosted application running on Java 7
CPU usage will start to rise from 'normal' levels, around 5-10% to 100% over the course of 20 minutes then stay between 90-100 and not drop, a restart of the app restores normality.
The 2 excerpts below were taken from 2 thread dumps with 10 minutes between them.
Cross referencing the entire dump with visualvm CPU profiler snapshots shows there are around 10 threads executing this area of code which seem to have spent the entire time in the method seen below.
The entire stack (which is huge & abbreviated below) is the same from both thread dumps for all 10 threads apart from the locked object reference.
I'd like to know what is going on here. Including why has the locked object reference changed?
Is the code stuck in a loop or is there a lock somewhere?
thread dump 1
"http-thread-pool-8080(3)" - Thread t#112
java.lang.Thread.State: RUNNABLE
at java.lang.Throwable.fillInStackTrace(Native Method)
at java.lang.Throwable.fillInStackTrace(Throwable.java:783)
- locked <2328e584> (a java.lang.InterruptedException)
at java.lang.Throwable.<init>(Throwable.java:250)
at java.lang.Exception.<init>(Exception.java:54)
at java.lang.InterruptedException.<init>(InterruptedException.java:57)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1325)
at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.tryLock(ReentrantReadWriteLock.java:873)
at com.sun.corba.ee.impl.oa.poa.POAImpl.acquireLock(POAImpl.java:390)
at com.sun.corba.ee.impl.oa.poa.POAImpl.readLock(POAImpl.java:422)
at com.sun.corba.ee.impl.oa.poa.POAImpl.enter(POAImpl.java:1743)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.getServantWithPI(CorbaServerRequestDispatcherImpl.java:302)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:196)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1624)
at com.sun.corba.ee.impl.protocol.SharedCDRClientRequestDispatcherImpl.marshalingComplete(SharedCDRClientRequestDispatcherImpl.java:126)
at com.sun.corba.ee.impl.protocol.CorbaClientDelegateImpl.invoke(CorbaClientDelegateImpl.java:273)
at com.sun.corba.ee.impl.protocol.CorbaClientDelegateImpl.is_a(CorbaClientDelegateImpl.java:395)
at org.omg.CORBA.portable.ObjectImpl._is_a(ObjectImpl.java:130)
...
thread dump 2
"http-thread-pool-8080(3)" - Thread t#112
java.lang.Thread.State: RUNNABLE
at java.lang.Throwable.fillInStackTrace(Native Method)
at java.lang.Throwable.fillInStackTrace(Throwable.java:783)
- locked <83c9c3a> (a java.lang.InterruptedException)
at java.lang.Throwable.<init>(Throwable.java:250)
at java.lang.Exception.<init>(Exception.java:54)
at java.lang.InterruptedException.<init>(InterruptedException.java:57)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1325)
at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.tryLock(ReentrantReadWriteLock.java:873)
at com.sun.corba.ee.impl.oa.poa.POAImpl.acquireLock(POAImpl.java:390)
at com.sun.corba.ee.impl.oa.poa.POAImpl.readLock(POAImpl.java:422)
at com.sun.corba.ee.impl.oa.poa.POAImpl.enter(POAImpl.java:1743)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.getServantWithPI(CorbaServerRequestDispatcherImpl.java:302)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:196)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1624)
at com.sun.corba.ee.impl.protocol.SharedCDRClientRequestDispatcherImpl.marshalingComplete(SharedCDRClientRequestDispatcherImpl.java:126)
at com.sun.corba.ee.impl.protocol.CorbaClientDelegateImpl.invoke(CorbaClientDelegateImpl.java:273)
at com.sun.corba.ee.impl.protocol.CorbaClientDelegateImpl.is_a(CorbaClientDelegateImpl.java:395)
at org.omg.CORBA.portable.ObjectImpl._is_a(ObjectImpl.java:130)
...
UPDATE
This is the POAImpl acquireLock method that may be causing the issue...
private void acquireLock(Lock lock) {
MethodMonitor __$mm$__ = (MethodMonitor)__$mm$__0.content();
if (__$mm$__ != null) {
__$mm$__.enter(1, new Object[]{lock});
}
try {
long timeout = 1L;
boolean locked = false;
boolean interrupted = false;
int count = 0;
int reportingThreshhold = 1;
while(!locked) {
if (count >= reportingThreshhold) {
this.acquireLockWaiting(count, __$mm$__, 1);
if (reportingThreshhold < 1073741823) {
reportingThreshhold *= 2;
}
}
try {
locked = lock.tryLock(1L, TimeUnit.SECONDS);
++count;
} catch (InterruptedException var13) {
interrupted = true;
}
if (interrupted) {
Thread.currentThread().interrupt();
}
}
if (__$mm$__ != null) {
__$mm$__.exit(1);
}
} finally {
if (__$mm$__ != null) {
__$mm$__.exit(1);
}
}
}
As for provided code. Its essentially doing something like this:
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
Thread t=new Thread(()->lock.lock()); //lets simulate that Lock is locked
t.start();
t.join();
int times = 0;
Thread.currentThread().interrupt(); //and for whatever reasons - thread was interrupted from outside
boolean locked=false;
while (!locked) {
try {
boolean gotLock=lock.tryLock(1, TimeUnit.SECONDS);
System.out.println("Got lock?: "+gotLock);
} catch (InterruptedException e) {
System.out.println("Thrown times:" + times++);
Thread.currentThread().interrupt(); // iterrupts again - will throw on getLock no matter what now
}
}
}
So basicly having interuption once - you will dive into limbo of infinite loop - without delays - which hogs the CPU. I would suggest adding diagnostic logging around that interuption handling to see what is happening.
One option is that something like that happens in code:
public void doTheJob(){
try{
.... // fail fast for whatever reason
}catch(Exception e){
doTheJob();
}
}
Exception occures - thats why we are seeing stacktracke. You got yourself an infinite loop.
What is very interesting is that there is an InterruptedException in the stacktrace, so it looks alike that you might try to kill some pending (timing out) tasks - and maybe reschedule them.
I would like to understand that does java actually run multiple threads in parallel in a multi core CPU, or there is context switching between threads and only one thread is active and others are waiting for their turn to run.
In other words, is there a possibility that 2 threads are running in parallel???
Because my Thread.currentThread() does not give me a array of threads, but only one thread which is running.
So what is the truth, does only one thread run at a time while others wait or multiple threads can run in parallel, if yes , then why my Thread.currentThread() method return only 1 thread object.
Edit : .....
I have created 2 classes to count numbers
1 class does it synchronously and the other one divides it into two halves and executes the two halves in 2 threads..(intel i5(4 CPUs), 8GB ram)
the code is as follows :
common class :
class Answer{
long ans = 0L;}
Multi Thread execution :
public class Sheet2 {
public static void main(String[] args) {
final Answer ans1 = new Answer();
final Answer ans2 = new Answer();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for(int i=0;i<=500000; i++) {
ans1.ans = ans1.ans + i;
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for(int i=500001;i<=1000000; i++) {
ans2.ans = ans2.ans + i;
}
}
});
long l1 = System.currentTimeMillis();
try {
t1.start();t2.start();
t1.join();
t2.join();
long l2 = System.currentTimeMillis();
System.out.println("ans :" + (ans1.ans + ans2.ans) +" in "+(l2-l1) +" milliseconds");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Single Thread execution :
public class Sheet3 {
public static void main(String[] args) {
final Answer ans1 = new Answer();
long l1 = System.currentTimeMillis();
for(int i=0;i<=1000000; i++) {
ans1.ans = ans1.ans + i;
}
long l2 = System.currentTimeMillis();
System.out.println("ans :" + (ans1.ans ) +" in "+(l2-l1) +" milliseconds"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
My Single thread execution is faster than my multi threaded execution, I though the context switching was putting a overhead on the execution initially and hence the multithreaded execution output was slower, now I am having muti core CPU (4 CPU), but still single threaded execution is faster in this example..
Can you please explain the scenario here... is it because my other processes are eating up the other cores and hence my threads are not running in parallel and performing time slicing on the CPU ???
Kindly throw some light on this topic.
Thanks in advance.
Cheers.!!!
In short yes it does run on separate threads. You can test it by creating 100 threads and checking in your process explorer it will say 100 threads. Also you can do some computation in each thread and you will see your multicore processor go upto 100% usage.
Thread.currentThread gives you the current thread you are running from.
When you start your program you are running on the "main" thread.
As soon as you start a new thread
new Thread(myRunnable);
any code located in the myRunnable will run on the new thread while your current thread is is still on the main Thread.
If you check out the API http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html it gives allot more detailed description of the thread.
The actual threading mechanism can vary between CPU architectures. But the real problem is that you're misinterpreting the method name. Thread.currentThread() doesn't return the thread executing at the current moment in time; it returns the thread currently executing the method call, that is, itself.
Yes it does. Run any simple infinite loop on more than one threads and you'll see the cpu usage > 100% on a multi-core CPU.
Yes it does run threads concurrently .That is the very purpose of the multithreading concept .you may find the folowing discussion helpful :
Current Thread Method java
Not a complete answer here, just adding to what others already have said:
The Java Language Specification does not require that threads run in parallel, but it allows them to do so. What actually happens in any given Java Virtual Machine depends on how that JVM is implemented.
Any practical JVM will create one "native" (i.e., operating system) thread for each Java thread, and let the operating system take care of scheduling, locking, waiting, notifying,...
I just started out with threading. I wrote a main class that sets up and starts 100 threads, waits 5 seconds and then interrupts them (at least that's what I thought it did):
public static void main(String[] args) {
List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < 100; i++) {
Thread t = new Thread(new Walker());
threads.add(t);
}
System.out.println("Starting threads...");
for (Thread thread : threads) {
thread.start();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// don't do anything
}
System.out.println("Time's up - Terminating threads...");
for (Thread t : threads) {
t.interrupt();
System.out.print(".");
}
for (Thread t : threads) {
try {
t.join(10);
} catch (InterruptedException e) {
// don't do anything
}
}
System.out.println("");
System.out.println("All done.");
}
The threads looked a bit like this:
public class Walker implements Runnable {
public void run() {
for (int i = 0;; i++) {
//do some complicated stuff that takes some time
System.out.println(Thread.currentThread().getName() + ":" + i);
if (Thread.interrupted()) {
break;
}
}
}
}
Now, the output I got was that the main thread began interrupting threads, but some sub threads continued to run a few times (i.e. loop iterations) before terminating, e.g.
Starting threads...
Thread-1:0
Thread-2:0
Thread-1:1
Thread-3:0
[...]
Time's up - Terminating threads...
......Thread-1:60
Thread-1:61
...Thread-1:62
Thread-2:55
..All done.
[output from threads sometimes continued even here - after the join()]
At that time I didn't fully understand that a single thread could be allocated enough processor time to run a few times - I expected at most one additional run before the main thread had the opportunity to interrupt it.
But while I now see that it is absolutely fine for a thread to be executed for some (long) time before the main thread gets a chance to terminate (i.e. interrupt) it, I am still wondering: is there an easy way to interrupt all child threads in a timely manner from the main thread? (Setting a "time to live" through a thread's constructor and then testing inside the Walker class for it is not what I want.)
Also: is it possible for the last print statement to execute and then see some output from individual threads - after all threads were join()ed? (Maybe I have a glitch somewhere else; the actual code is a bit more complex...)
The problem you observe is probably due to how System.out.println works. It is a synchronized method. So a likely explanation is:
when calling System.out.print("."); after t.interrupt();, your main thread acquires the lock to print
before the lock is released, worker threads arrive at System.out.println(Thread.currentThread().getName() + ":" + i); and wait for the lock
when the main thread releases the lock, all the worker threads that were waiting print their progress.
the main thread arrives at System.out.print("."); again and has to wait for the print lock to be available, etc.
Regarding the fact that you see more prints from the worker threads after "All Done" is printed: you only join for 10 ms, so it is possible that it is not enough and a thread is not finished within 10ms of being interrupted. If you just use join() you should not see that any longer.
Example of Worker class that reproduces the behaviour you observe:
class Walker implements Runnable {
public void run() {
for (int i = 0;; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
//do not respond to interruption too quickly on purpose
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + ":" + i);
if (Thread.interrupted()) {
break;
}
}
}
}
It would be easier with ExecutorService, eg
int nThreads = 100;
ExecutorService ex = Executors.newFixedThreadPool(nThreads);
for (int i = 0; i < nThreads; i++) {
ex.execute(new Walker());
}
Thread.sleep(5000);
ex.shutdownNow();
Maybe I have a glitch somewhere else; the actual code is a bit more complex...
Yes it is a glitch, unfortunately isn't a simple set 1 property, java side.
If the code is commercial, complex, than you can allocate a bit more time to write some native libraries, for major Os type. With that help you can easily play with threads as you wanted.
The first times has an overhead for developing and understanding how the threads are woking in native, os side, than just call a function with a few params :)
Not sure, if is helping, the glitch exists.
I have a portion of code dealing with threads and I want to understand its function in detail. The run method is empty in my example, but lets assume it has some operations to do on a global variable:
import java.io.File;
public class DigestThread extends Thread {
private File input;
public DigestThread(File input) {
this.input = input;
}
public void run() {
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
File f = new File(args[i]);
Thread t = new DigestThread(f);
t.start();
}
}
}
After creating a thread and starting it, will it wait to finish the tasks in the run method before creating/running another thread ?
second question
if a variable has declared in run method that means it will be declared many times because every thread created will do the task in run method , is every thread handles its own varible although variable in each thread are same ?
will it waitng for finish the tasks in run method to creat another
method ?
No. That's the whole point of Multithreading. Every thread has it's own stack of execution. So, when you start a thread, it enters the run() method, and executes it in a different stack, and at the same time the main thread continues execution, in it's own stack.
After that, main thread, can spawn another thread. Thus all the threads run simultaneously, but of course, one at a time, sharing the CPU amongst them, based on the specific CPU allocation algorithm being used.
It's not possible to write down all the details about the execution process of multiple threads here. I would rather suggest to read some tutorials or search for some online resources, regarding the concept of Multithreading. Once clear in concept, move ahead with the implementation in Java.
Here's some tutorials links you can start with: -
Thread Wiki Page
SO Multithreading Wiki Page
Concurrency - Oracle Tutorial
http://www.vogella.com/articles/JavaConcurrency/article.html
Once you start a thread, it will run in a separate thread and the main() thread will continue (it may end before the child thread ends).
If you want the thread to finish before main then you can use the Thread.join method on thread to wait for it.
First, Thread is a single sequential flow of control within a program.
We can execute more than one thread in a program, but there is a life cycle, where you can find out how threads work...
Whenever we call the start() method of Thread it automatically calls the overriden method public void run() and executes the code of the run() method...
Here is a simple example of Thread in Java with ABC and XYZ thread classes
/* Write a program to print having two Thread Class 1) ABC with 1 second 2) XYZ 2 second. 10 times with Extend Constructor */
class ABCThreadConstructor extends Thread {
ABCThreadConstructor(String name) {
super(name);
}
public void run() {
try {
for(int i = 0; i < 10; i++) {
System.out.println("ABC");
Thread.sleep(1000);
}
} catch(InterruptedException ie) {
System.out.println("Interrupted Exception : "+ie);
}
}
}
class XYZThreadConstructor extends Thread {
XYZThreadConstructor(String name) {
super(name);
}
public void run() {
try{
for(int i = 0; i < 10; i++) {
System.out.println("XYZ");
Thread.sleep(2000);
}
} catch(InterruptedException ie) {
System.out.println("Interrupted Exception : "+ie);
}
}
}
class AbcXyzThreadConstructorDemo {
public static void main(String args[]) {
ABCThreadConstructor atc = new ABCThreadConstructor("ABCThreadConstructor");
System.out.println("Thread Name : " + atc.getName());
atc.start();
XYZThreadConstructor xtc = new XYZThreadConstructor("XYZThreadConstructor");
System.out.println("Thread Name : " + xtc.getName());
xtc.start();
}
}
Assuming your question is "After creating a thread and starting it, will the program wait for the thread to finish its run method before creating another thread?"
If that's the case, No the program will not wait. t.start() kicks off the thread and it gets its own chunk of memory and thread priority to run. It will do its operations and then exist accordingly. Your main thread will start the number of threads specified in args before terminating.
If you need the application to wait on the thread then use t.join(). That way the parent thread (the one that runs main) will be joined to the child thread and block until its operation is complete. In this case it sort of defeats the purpose of threading but you can store the thread ID for whatever logic you need and join() later.
I was going through threads and I read that ..The notify() method is used to send a signal to one and only one of the threads that are waiting in that same object's waiting pool.
The method notifyAll() works in the same way as notify(), only it sends the signal to all of the threads waiting on the object.
Now my query is that if Lets say I have 5 threads waiting and through Notify() , i want to send to notification to thread 3 only, what logic should be there that notification is sent to thread 3 only ..!!
You can't directly do this with wait and notify. You'd have to set a flag somewhere, have the code in the thread check it and go back to waiting if it's the wrong thread, and then call notifyAll.
Note that if you have to deal with this, it might be a sign that you should restructure your code. If you need to be able to notify each individual thread, you should probably make each of them wait on a different object.
wait-notify is rather a low level mechanism to indicate to other threads that an event (being expected occured). Example of this is producer/consumer mechanism.
It is not a mechanism for threads to communicate to each other.
If you need something like that you are looking in the wrong way.
The following code starts up five threads and sets the third one a flag which tells it that it is the only to continue. Then all of the threads that are waiting on the same lock object lock are notified (woken-up), but only the one selected continues. Be careful, writing multi-threaded applications is not easy at all (proper synchronization, handling the spurious wake-ups, etc.) You should not need to wake up only one particular thread from the group as this points to an incorrect problem decomposition. Anyway, here you go...
package test;
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.start(5);
}
private void start(int n) {
MyThread[] threads = new MyThread[n];
for (int i = 0; i < n; i++) {
threads[i] = new MyThread();
/* set the threads as daemon ones, so that JVM could exit while they are still running */
threads[i].setDaemon(true);
threads[i].start();
}
/* wait for the threads to start */
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
/* tell only the third thread that it is able to continue */
threads[2].setCanContinue(true);
/* wake up all threads waiting on the 'lock', but only one of them is instructed to continue */
synchronized (lock) {
lock.notifyAll();
}
/* wait some time before exiting, thread two should be able to finish correctly, the others will be discarded with the end of the JVM */
for (int i = 0; i < n; i++) {
try {
threads[i].join(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("Done!");
}
/** synchronization object, i.e. a lock which makes sure that only one thread can get into "Critical Section" */
private final Object lock = new Object();
/** A simple thread to demonstrate the issue */
private final class MyThread extends Thread {
private volatile boolean canContinue;
#Override
public void run() {
System.out.println(Thread.currentThread().getName() + " going to wait...");
synchronized (lock) {
while (!canContinue) {
try {
lock.wait(1000); /* one second */
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
System.out.println(Thread.currentThread().getName() + " woken up!");
}
public void setCanContinue(boolean canContinue) {
this.canContinue = canContinue;
}
};
}
The output of the code is:
Thread-0 going to wait...
Thread-2 going to wait...
Thread-3 going to wait...
Thread-1 going to wait...
Thread-4 going to wait...
Thread-2 woken up!
Done!
So you can clearly see that only the third thread (indexed from zero) is woken up. You have to study the Java synchronization and multi-threading in more detail to understand every particular line of the code (for example, here).
I would like to help you more, but I would have to write almost a book about Java threads and that is why I just pointed out to this Java Tutorial on threads. You are right, this problematics is not easy at all, especially for beginners. So I advise you to read through the referenced tutorial and then you should be able to understand most of the code above. There is no easy way around or at least I do not know of any.