I would like to make a simple thread program that starts 3 threads in order 1,2,3 and after that stops in order 3,2,1 just by using the sleep() method. However, everytime the threads start in different order.
class Thread1 extends Thread{
public void run(){
System.out.println("Thread 1 running...");
try {
this.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Thread 1 has terminated");
}
}
class Thread2 extends Thread {
public void run(){
System.out.println("Thread 2 running...");
try {
this.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Thread 2 has terminated");
}
}
class Thread3 extends Thread {
public void run(){
System.out.println("Thread 3 running...");
try {
this.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Thread 3 has terminated");
}
}
public static void main(String[] args) throws InterruptedException {
Thread tr1 = new Thread1();
Thread tr2 = new Thread2();
Thread tr3 = new Thread3();
tr1.start();
tr2.start();
tr3.start();
}
current output:
Thread 1 running...
Thread 3 running...
Thread 2 running...
Thread 3 has terminated
Thread 2 has terminated
Thread 1 has terminated
desired output:
Thread 1 running...
Thread 2 running...
Thread 3 running...
Thread 3 has terminated
Thread 2 has terminated
Thread 1 has terminated
Your threads are started in right order, but output can be wrong because output messages arrive concurrently. You should move messaging into the main thread:
public static void main(String[] args) throws InterruptedException {
Thread tr1 = new Thread1();
Thread tr2 = new Thread2();
Thread tr3 = new Thread3();
tr1.start();
System.out.println("Thread 1 started");
tr2.start();
System.out.println("Thread 2 started");
tr3.start();
System.out.println("Thread 3 started");
}
You can make Util class, witch must be thread safe, and make synchronized method to print.
public class Utils {
public static synchronized void printStuff(String msg) {
System.out.println(msg);
}
}
Now in Thread1, Thread2 and Thread3 use this Utils.printStuff("Text") to print in console.
Related
I am trying to learn multithreading and was trying with a cyclic barrier. I understand that to break the barrier an await method must be called by the number of the thread mentioned while creating the barrier. I am trying to do the same but when I check if the barrier is broke my main method is going in an infinite loop.
class CyclicBarrierTrial implements Runnable{
CyclicBarrier barrier;
public CyclicBarrierTrial(CyclicBarrier barrier){
this.barrier=barrier;
}
public void run() {
System.out.println("in the run method");
try {
Thread.sleep(1000);
System.out.println("going to call awake on barrier"+ Thread.currentThread().getName());
try {
barrier.await();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("barrier broke");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//System.out.println("Wake up from the Sleep"+ Thread.currentThread().getName());
}
}
public class MYCountDownLatch {
public static void main(String[] args) throws InterruptedException {
CyclicBarrier barrier = new CyclicBarrier(2);
Thread t1= new Thread(new CyclicBarrierTrial((barrier)));
t1.start();
Thread t2= new Thread(new CyclicBarrierTrial((barrier)));
Thread.sleep(2000);
t2.start();
while(!barrier.isBroken())
{
System.out.println("waiting for the barrier to break "+barrier.isBroken());
}
System.out.println("MAIN THREAD finally barrier to broke ");
}
}
barrier.isBroken() indicates if barrier is in broken state, which is different than barrier is tripper.
To check this, you can try interrupting one of thread, this will raise BarrierBrokenException on other threads and barrier.isBroken() will be true.
Thread.currentThread().interrupt();
If you want to wait for all threads to complete, then you can use ExecutorService.awaitTermination or Thread.join
From documentation:
If any thread is interrupted while waiting, then all other waiting threads will throw BrokenBarrierException and the barrier is placed in the broken state.
Hope this help.
I'm unable to make out the difference. I read this: actual-use-of-lockinterruptibly-for-a-reentrantlock
and wanted to test it. Here goes the code:
public class Test {
public static void main(String[] args){
Test test = new Test();
test.inturreptWork();
//Main group
System.out.println("Main Thread group: "+Thread.currentThread().getThreadGroup().getName());
//System group is the parent of main group. it contains system level threads like finalizer,signal dispatcher,attach listener
System.out.println("Main Thread group: "+Thread.currentThread().getThreadGroup().getParent());
}
public void inturreptWork(){
Inturrept inturrept= new Inturrept();
Thread t1 = new Thread(inturrept,"Thread 1");
Thread t2 = new Thread(inturrept,"Thread 2");
Thread t3 = new Thread(inturrept,"Thread 3");
try{
t1.start();
Thread.sleep(1000);
t2.start();
Thread.sleep(1000);
t2.interrupt();
t3.start();
t1.join();
t2.join();
t3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
System.out.println("Finally");
}
}
Here is the Inturrept Class
public class Inturrept implements Runnable {
Lock lock = new ReentrantLock();
#Override
public void run() {
try {
System.out.println("Trying to get lock ,Thread name is: " + Thread.currentThread().getName());
lock.lock();// or lock.lockInterruptibly();
System.out.println("Running");
Thread.sleep(7000);// Use something else to mimic sleep as it throws interrupted exception
lock.unlock();// This caused IllegalMonitorStateException
} catch (InterruptedException e) {
System.out.println("I was inturrepted, Thread name is: " + Thread.currentThread().getName());
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
Console Output:
Trying to get lock ,Thread name is: Thread 1
Running
Trying to get lock ,Thread name is: Thread 2
Trying to get lock ,Thread name is: Thread 3
Running
Exception in thread "Thread 1" I was inturrepted, Thread name is: Thread 2
java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
at com.test.main.Inturrept.run(Inturrept.java:21)
at java.lang.Thread.run(Thread.java:748)
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.test.main.Inturrept.run(Inturrept.java:15)
at java.lang.Thread.run(Thread.java:748)
Running
Exception in thread "Thread 3" Finallyjava.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
at com.test.main.Inturrept.run(Inturrept.java:21)
at java.lang.Thread.run(Thread.java:748)
Main Thread group: main
Main Thread group: java.lang.ThreadGroup[name=system,maxpri=10]
As mentioned in the answer "This is the same as with regular lock(). But if another thread interrupts the waiting thread lockInterruptibly() will throw InterruptedException."
Even if it's lock.lock() or lock.lockinterruptibly(). The thread gets interrupted. so what's the difference? did i understand something wrong please assist.
Also another question I've is why do I see "Exception in thread "Thread 3" in console. It ran as I can see two "runnings" in logs.
Thanks you.
lockInterruptibly() first check if thread is interrupted or not.If interrupted then throw InterruptedException
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
lock.unlock() is calling twice in your code .so it is throwing IllegalMonitorStateException because not same thread is doing unlock.When the thread do the unlock without lock it throw the exception.
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
Thread.sleep causing the interrupt exception.Sleep method throw InterruptedException
void sleep(long millis) throws InterruptedException
Modified code
public void run() {
try {
System.out.println("Trying to get lock ,Thread name is: " + Thread.currentThread().getName());
lock.lock();
System.out.println("Running");
//Thread.sleep(7000);
} catch (Exception e) {
System.out.println("I was inturrepted, Thread name is: " + Thread.currentThread().getName());
e.printStackTrace();
} finally {
lock.unlock();
}
}
class JoinDemo extends Thread {
JoinDemo(String nm) {
setName(nm);
start();
}
public void run() {
for (int i = 1; i <= 5; i++) {
try {
Thread.sleep(100);
} catch (Exception e) {
System.out.println(e);
}
System.out.println(i);
}
System.out.println(getName() + " exiting.");
}
public static void main(String args[]) {
JoinDemo t1 = new JoinDemo("One");
JoinDemo t2 = new JoinDemo("Two");
JoinDemo t3 = new JoinDemo("Three");
try {
t1.join();
} catch (Exception e) {
System.out.println(e);
}
System.out.println("Main Thread Exits now.");
}
}
The output obtained is:
1
1
1
2
2
2
3
3
3
4
4
4
5
5
Three exiting.
One exiting.
5
Main Thread Exiting
Two exiting.
I wrote the above program after going through various sites to understand the concept of Join(). But still i'm unable to get it.The problem I'm facing is that I have used t1.join(). So thread one should exit before three, but here thread three exits before one. And every time I run the program the output is different. As sometimes it is two exiting before one, or three before one. Shouldn't thread one exit before any other thread?? As t1.join() waits for thread one to terminate before three and one??
No you mistook the effect of join().
when you do a t1.join()you are just asserting that the thread t1 will be finished before continuing the program.
As you can see it's what you have,
One exiting.
5
Main Thread Exiting
One exit before the end of the main symbolized by the Main Thread Exiting.
If you want your program to finish all the thread before finishing you should do :
try {
t1.join();
t2.join();
t3.join();
} catch (Exception e) {
System.out.println(e);
}
If you want One to finish then 2 then 3
JoinDemo t1 = new JoinDemo("One");
try {
t1.join();
} catch (Exception e) { System.out.println(e); }
JoinDemo t2 = new JoinDemo("Two");
try {
t2.join();
} catch (Exception e) { System.out.println(e); }
JoinDemo t3 = new JoinDemo("Three");
try {
t3.join();
} catch (Exception e) { System.out.println(e); }
To know exactly what join() is doing,
JoinDemo t1=new JoinDemo("One");
t1.join();
JoinDemo t2=new JoinDemo("Two");
JoinDemo t3=new JoinDemo("Three");
Just call the method after declaring t1 and see.
join() method will make the already initialized Thread to complete first.So other Threads will wait till then.
t1.join() simply ensures that your main thread will block until t1 has completed. You have no control over how quickly t1 will finish compared to the other two threads.
t1, t2 and t3 are at the mercy of the thread scheduler. The only guarantee you have in your code is that t1 will finish before the main thread.
You are running 3 different threads. The priority or amount of CPU used for each thread depends on the java implementation, in some cases it's done by the OS. That's why you get a different output.
Joins makes the running thread wait until the joint thread dies.
I think you want this output:
class JoinDemo extends Thread {
JoinDemo(String nm) {
setName(nm);
}
public void run() {
for (int i = 1; i <= 5; i++) {
try {
Thread.sleep(100);
} catch (Exception e) {
System.out.println(e);
}
System.out.println(i);
}
System.out.println(getName() + " exiting.");
}
public static void main(String args[]) {
JoinDemo t1 = new JoinDemo("One");
JoinDemo t2 = new JoinDemo("Two");
JoinDemo t3 = new JoinDemo("Three");
try {
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();
} catch (Exception e) {
System.out.println(e);
}
System.out.println("Main Thread Exits now.");
}
}
public class TwoThreads {
private static Object resource = new Object();
private static void delay(long n) {
try
{
Thread.sleep(n);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.print("StartMain ");
new Thread1().start();
delay(1000); //dealay 1
Thread t2 = new Thread2();
t2.start();
delay(1000); // delay 2
t2.interrupt(); //step 7
delay(1000); //delay 3
System.out.print("EndMain ");
}
static class Thread1 extends Thread {
public void run() {
synchronized (resource) {
System.out.print("Startl ");
delay(6000);
System.out.print("End1 ");
}
}
}
static class Thread2 extends Thread {
public void run() {
synchronized (resource) {
System.out.print("Start2 ");
delay(2000);
System.out.print("End2 ");
}
}
}
}
At step 7 (as I have marked), main thread calls interrupt() on thread t2, but as it was waiting to acquire the lock on a resource, it doesn't throw any exception. After that, main thread prints "End Main" after waiting 1000 ns. In other words, main thread has completed its task, so what triggers t2.interrupt() again because it throws exception after that?
Here is how your program runs, with timestamps:
0000 StartMain
0000 Startl
3000 EndMain
6000 End1
6000 Start2
6000 End2
Why (timestamps in brackets)?
[0000] main launches Thread1, which acquires a lock and sleeps for 6 seconds
[1000] main launches Thread2, which can't acquire the lock held by Thread1 for 6 seconds
[2000] main interrupts Thread2 setting its interrupted flag to true, but Thread2 is waiting for a lock and does not do anything about it
[3000] main ends
[6000] Thread1 finishes sleeping and releases the lock
[6000] Thread2 can acquire it and starts to sleep (its interrupted flag is still on)
[6000] sleep detects that Thread2 has been interrupted and throws an exception immediately
[6000] Thread2 finishes, allowing the JVM to exit
You need a ReentrantLock.
public class TwoThreads {
private static Lock lock = new ReentrantLock();
private static void delay(long n) {
try {
Thread.sleep(n);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.print("StartMain ");
new Thread1().start();
delay(1000); //dealay 1
Thread t2 = new Thread2();
t2.start();
delay(1000); // delay 2
t2.interrupt(); //step 7
delay(1000); //delay 3
System.out.print("EndMain ");
}
static class Thread1 extends Thread {
public void run() {
try {
lock.lockInterruptibly();
try {
System.out.print("Startl ");
delay(6000);
System.out.print("End1 ");
} finally {
lock.unlock();
}
} catch (InterruptedException ex) {
// Interrupted.
}
}
}
static class Thread2 extends Thread {
public void run() {
try {
lock.lockInterruptibly();
try {
System.out.print("Start2 ");
delay(2000);
System.out.print("End2 ");
} finally {
lock.unlock();
}
} catch (InterruptedException ex) {
// Interrupted.
}
}
}
}
Prints:
StartMain Startl EndMain End1
It´s because the JVM kills your threads when the main thread is shutting down.
I wanted to verify in my own eyes the different between sleep and wait.
Wait can only be done in a synchronized block because it releases the ownership of the monitor lock.
While sleep is not related to the monitor lock and a thread that is already the owner of the monitor lock shouldn't lose its ownership if sleeping.
For that i made a test:
Steps:
Started a thread that waits in a synched block for 5 secs.
Waited 3 secs and started another thread that acquires the monitor lock (because Thread-A is waiting) and simply sleeps for 5 secs while holding the monitor lock.
Expected result:
Thread - A will only re-acquire the lock after 8 seconds, When Thread - B finally releases the monitor lock by exiting the synch block.
Actual result.
Thread - A acquires the monitor lock after 5 seconds.
Can some1 explain to me what happened here?
public static void main(String[] args) {
Runnable r1 = new Runnable() {
#Override
public void run() {
System.out.println("r1 before synch block");
synchronized (this) {
System.out.println("r1 entered synch block");
try {
wait(5000);
System.out.println("r1 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Runnable r2 = new Runnable() {
#Override
public void run() {
System.out.println("r2 before synch block");
synchronized (this) {
System.out.println("r2 entered synch block");
try {
Thread.currentThread();
Thread.sleep(5000);
//wait(5000);
System.out.println("r2 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
try {
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
Thread.currentThread();
Thread.sleep(3000);
t2.start();
t1.join();
t2.join();
System.out.println(Thread.currentThread().getName() + " Finished joining");
} catch (Exception e) {
e.printStackTrace();
}
}
EDIT:
Ok I understand my error - I waiting on this - r1/r2 and not on the same object.
Now I changed it and both acquire on the same object - The class instance of Main.
1. r1 acquires ownership of the monitor lock of Main.this
2. r1 Releases it.
3. When r1 tries to re-acquire it I get an exception:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at Main$1.run(Main.java:28)
at java.lang.Thread.run(Unknown Source)
on synchronized (Main.this)
What is the problem here?
public static void main(String[] args) {
Main main = new Main();
main.test();
}
public void test() {
Runnable r1 = new Runnable() {
#Override
public void run() {
System.out.println("r1 before synch block");
synchronized (Main.this) {
System.out.println("r1 entered synch block");
try {
wait(5000);
System.out.println("r1 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Runnable r2 = new Runnable() {
#Override
public void run() {
System.out.println("r2 before synch block");
synchronized (Main.this) {
System.out.println("r2 entered synch block");
try {
Thread.currentThread();
Thread.sleep(5000);
//wait(5000);
System.out.println("r2 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
try {
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
Thread.currentThread();
Thread.sleep(3000);
t2.start();
t1.join();
t2.join();
System.out.println(Thread.currentThread().getName() + " Finished joining");
} catch (Exception e) {
e.printStackTrace();
}
}
The two threads actually hold two different locks. Say your class name is MyClass, change two lines of synchronized (this) to synchronized (MyClass.this), that makes the two threads to hold same lock.
here's a much better way to make the test work , and show that it works .
your problem was that you didn't wait correctly and used Thread.currentThread() for no reason .
btw, in case you want to use signalling of the wait-notifier mechanism without losing the signal , i suggest you read this link.
public class MAIN
{
public static void main(final String[] args)
{
final Object sync =new Object();
final long startTime=System.currentTimeMillis();
final Runnable r1=new Runnable()
{
#Override
public void run()
{
System.out.println((System.currentTimeMillis()-startTime)/1000+": r1 before synch block");
synchronized(sync)
{
System.out.println((System.currentTimeMillis()-startTime)/1000+": r1 entered synch block");
try
{
sync.wait(5000);
System.out.println((System.currentTimeMillis()-startTime)/1000+": r1 finished waiting");
}
catch(final InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println((System.currentTimeMillis()-startTime)/1000+": r1 exited synch block");
}
};
final Runnable r2=new Runnable()
{
#Override
public void run()
{
System.out.println((System.currentTimeMillis()-startTime)/1000+": r2 before synch block");
synchronized(sync)
{
System.out.println((System.currentTimeMillis()-startTime)/1000+": r2 entered synch block");
try
{
Thread.sleep(5000);
System.out.println((System.currentTimeMillis()-startTime)/1000+": r2 finished waiting");
}
catch(final InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println((System.currentTimeMillis()-startTime)/1000+": r2 exited synch block");
}
};
try
{
final Thread t1=new Thread(r1);
final Thread t2=new Thread(r2);
t1.start();
Thread.sleep(3000);
t2.start();
t1.join();
t2.join();
System.out.println((System.currentTimeMillis()-startTime)/1000+": Finished joining");
}
catch(final Exception e)
{
e.printStackTrace();
}
}
}