One of my friends showed me his code below, and I thought the two threads could be deadlocked, because they could deadlock while trying to acquire locks on the different variables: sb1 and sb2.
When I run the code, they don't seem to be deadlocked, as I was able to see the output:
A
B
second thread: AB
second thread: BA
Code below:
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
new Thread() {
public void run() {
synchronized (sb1) {
sb1.append("A");
synchronized (sb2) {
sb2.append("B");
System.out.println(sb1.toString());
System.out.println(sb2.toString());
}
}
}
}.start();
new Thread() {
public void run() {
synchronized (sb2) {
sb2.append("A");
synchronized (sb1) {
sb1.append("B");
System.out.println("second thread: " + sb1.toString());
System.out.println("second thread: " + sb2.toString());
}
}
}
}.start();
}
so could the two threads be deadlocked?
The code you posted has a potential deadlock. If it runs successfully, that just means you got lucky.
To demonstrate the potential deadlock, you can rig the timing to ensure that a deadlock occurs.
public static void main(String[] args) {
final StringBuilder sb1 = new StringBuilder();
final StringBuilder sb2 = new StringBuilder();
new Thread() {
public void run() {
synchronized (sb1) {
sb1.append("A");
System.out.println("Thread 1 has sync sb1");
try { Thread.sleep(700); }
catch (InterruptedException e) { e.printStackTrace(); return; }
System.out.println("Waiting for thread 1 to sync sb2");
synchronized (sb2) {
sb2.append("B");
System.out.println(sb1.toString());
System.out.println(sb2.toString());
}
}
}
}.start();
new Thread() {
public void run() {
try { Thread.sleep(500); }
catch (InterruptedException e) { e.printStackTrace(); return; }
synchronized (sb2) {
System.out.println("Thread 2 has sync sb2");
sb2.append("A");
System.out.println("Waiting for thread 2 to sync sb1");
synchronized (sb1) {
sb1.append("B");
System.out.println("second thread: " + sb1.toString());
System.out.println("second thread: " + sb2.toString());
}
}
}
}.start();
}
Now the first thread will definitely get the sync on sb1, and the second will get the sync on sb2, and then you will get a deadlock.
Output:
Thread 1 has sync sb1
Thread 2 has sync sb2
Waiting for thread 2 to sync sb1
Waiting for thread 1 to sync sb2
The fact that you are not getting a deadlock does not imply a deadlock cannot occur.
You are right in inferring that a deadlock might occur when two threads attempt to acquire monitors on two different resources in opposite orders.
Therefore, this code may produce a deadlock.
However, if any of the two threads manages to acquire both the monitors before the other, no deadlock will occur (which seems to be happening with your execution).
Here's how a deadlock might occur instead:
Thread one starts and acquires lock on sb1
Thread two starts and acquires lock on sb2
Thread one waits to acquire lock on sb2, which is owned by thread two
Thread two waits to acquire lock on sb1, which is owned by thread one
As no thread will release its lock and both wait on the other, you get a deadlock.
Note: as Khelwood advises, forcing the threads to sleep may prevent one of the threads from acquiring both locks first, hence producing the deadlock.
That code explains exactly a simple deadlock.
The easiest way to tell is basically because your Threads hold circular dependencies between each other.
This code alot of the times will result in a deadlock.
Yes, your program can end in a deadlock. Here a more dynamic example based on the answer of #khelwood. It adds some delay to the actual string appending and repeats it in a while loop. So you can see what is happening, sooner or later the program will end in a deadlock. To identify the deadlock situation ThreadMXBean.findDeadlockedThreads() is used.
package stack43323164;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.List;
import java.lang.management.ThreadInfo;
public class HowToDemonstrateDeadlock {
private static List<ThreadInfo> findDeadlocks() {
ThreadMXBean tmxb = ManagementFactory.getThreadMXBean();
long[] result = tmxb.findDeadlockedThreads();
if (result == null)
return java.util.Collections.emptyList();
return java.util.Arrays.asList(tmxb.getThreadInfo(result, 2));
}
public static void main(String[] args) {
final StringBuilder sb1 = new StringBuilder();
final StringBuilder sb2 = new StringBuilder();
long monitorDelay=1000L;
//You can play with the delay times to modify the results
long threadOneDelay=100L;
long threadTwoDelay=100L;
new Thread() {
public void run() {
try {
while (true) {
synchronized (sb1) {
sb1.append("A");
System.out.println("Thread 1 has sync sb1");
System.out.println("Waiting for thread 1 to sync sb2");
synchronized (sb2) {
sb2.append("B");
System.out.println(sb1.toString());
System.out.println(sb2.toString());
}
}
Thread.sleep(threadOneDelay);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
new Thread() {
public void run() {
try {
while (true) {
synchronized (sb2) {
System.out.println("Thread 2 has sync sb2");
sb2.append("A");
System.out.println("Waiting for thread 2 to sync sb1");
synchronized (sb1) {
sb1.append("B");
System.out.println("second thread: " + sb1.toString());
System.out.println("second thread: " + sb2.toString());
}
}
Thread.sleep(threadTwoDelay);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
new Thread() {
public void run() {
try {
while (true) {
List<ThreadInfo> deadlocks = findDeadlocks();
if (!deadlocks.isEmpty()) {
for (ThreadInfo i : deadlocks) {
System.out.println("Deadlock detected on thread " + i.getThreadId() + "\n" + i);
}
//Not a chance to solve the situation - boom
System.exit(1);
} else {
System.out.println("No deadlock so far.");
}
Thread.sleep(monitorDelay);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
}
Related
public class MyVisibility {
private static int count = 0;
private static Object lock = new Object();
public static void main(String[] args) {
new MyVisibility.thread1().start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
return;
}
new MyVisibility.thread2().start();
}
static class thread1 extends Thread {
int i = 0;
#Override
public void run() {
super.run();
while (true) {
synchronized (lock) {
count++;
System.out.println("Thread one count is " + count);
try {
lock.wait();
System.out.println("i am notified");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count > 5) {
return;
}
}
}
}
static class thread2 extends Thread {
int i = 10;
#Override
public void run() {
super.run();
while (true) {
synchronized (lock) {
count++;
System.out.println("Thead 2 count is " + count);
lock.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count > 10) {
return;
}
}
}
}
}
In above code,
Current result on execution : I can see lock.notify() is getting called only after end of the while loop.
My assumption is Since lock.notify() is getting called immediately after count variable getting incremented, and immediately it should notify the waiting thread to resume its execution, instead after second thread completion of execution call is going for waiting thread to resume, what is the reason for this, can someone correct me what was wrong with my understanding.
Thank you.
Your deduction - "I can see lock.notify() is getting called only after end of the while loop" is not entirely correct. Try running multiple times, or put break point just after synchronized block of thread2, and then you will see thread1 "i am notified" being printed.
From documentation of notify() -
The awakened thread will not be able to proceed until the current
thread relinquishes the lock on this object
In your case before thread2 relinquishes lock and then thread1 acquires lock, thread2 acquires lock again by going into synchronized block.
While this might look like a repeat question, there is not ONE correct working implementation of the Reader Writer's problem in the internet using semaphores in Java. The closest I found was this where an alternative is given as the answer but not using semaphores.
I am new to multi-threading in Java so please bear with me. Here is my code:
import java.util.concurrent.Semaphore;
class ReaderWritersProblem {
static Semaphore readLock = new Semaphore(1);
static Semaphore writeLock = new Semaphore(1);
static int readCount = 0;
static class Read implements Runnable {
#Override
public synchronized void run() {
try {
readLock.acquire();
readCount++;
if (readCount == 1) {
writeLock.acquire();
}
System.out.println("Thread "+Thread.currentThread().getName() + " is READING");
Thread.sleep(1500);
System.out.println("Thread "+Thread.currentThread().getName() + " has FINISHED READING");
readLock.release();
readCount--;
if(readCount == 0) {
writeLock.release();
}
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
static class Write implements Runnable {
#Override
public synchronized void run() {
try {
writeLock.acquire();
System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
Thread.sleep(2500);
System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
writeLock.release();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
public static void main(String[] args) throws Exception {
Read read = new Read();
Write write = new Write();
Thread t1 = new Thread(read);
t1.setName("thread1");
Thread t2 = new Thread(read);
t2.setName("thread2");
Thread t3 = new Thread(write);
t3.setName("thread2");
Thread t4 = new Thread(read);
t4.setName("thread4");
t1.run();
t2.run();
t3.run();
t4.run();
}
}
I am creating 4 threads, 3 for reading and 1 for writing. However, the output is as such:
Thread main is READING Thread main has FINISHED READING Thread
main is READING Thread main has FINISHED READING Thread main
is WRITING Thread main has finished WRITING Thread main is
READING Thread main has FINISHED READING
The thread name being returned is 'main'. Also, all of these are seemingly not being executed concurrently. How do I correct this implementation of Reader Writers problem using Semaphores only? Using ReentrantReadLock etc would simply this but beat the purpose of the question, which clearly says implement the problem using semaphores. Thanks
Edit: Also, HOW do I show multiple threads reading? I am getting the execution results one by one.
EDIT: CORRECTED CODE: I have corrected the algorithm. Would like some review on this.
import java.util.concurrent.Semaphore;
class ReaderWritersProblem {
static Semaphore readLock = new Semaphore(1);
static Semaphore writeLock = new Semaphore(1);
static int readCount = 0;
static class Read implements Runnable {
#Override
public void run() {
try {
//Acquire Section
readLock.acquire();
readCount++;
if (readCount == 1) {
writeLock.acquire();
}
readLock.release();
//Reading section
System.out.println("Thread "+Thread.currentThread().getName() + " is READING");
Thread.sleep(1500);
System.out.println("Thread "+Thread.currentThread().getName() + " has FINISHED READING");
//Releasing section
readLock.acquire();
readCount--;
if(readCount == 0) {
writeLock.release();
}
readLock.release();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
static class Write implements Runnable {
#Override
public void run() {
try {
writeLock.acquire();
System.out.println("Thread "+Thread.currentThread().getName() + " is WRITING");
Thread.sleep(2500);
System.out.println("Thread "+Thread.currentThread().getName() + " has finished WRITING");
writeLock.release();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
public static void main(String[] args) throws Exception {
Read read = new Read();
Write write = new Write();
Thread t1 = new Thread(read);
t1.setName("thread1");
Thread t2 = new Thread(read);
t2.setName("thread2");
Thread t3 = new Thread(write);
t3.setName("thread3");
Thread t4 = new Thread(read);
t4.setName("thread4");
t1.start();
t3.start();
t2.start();
t4.start();
}
}
I assume that your question is related to why this code is not executing concurrently. This is because you have to call the method t1.start() and not t1.run() (and correspondingly so for all your other threads). t1.run() will run the run() method in the context of main thread and not in a new thread.
And I don't see the point of synchronized methods when you are already guarding the code with a binary semaphore. Two threads will not be able to simultaneously acquire a binary semaphore and as long as threads are not releasing the semaphore blindly your code will be safe. This defeats the whole prupose of having multiple reader threads.
Updated for the new question in comment - If you want multiple reader threads to access the same section then you should not use a binary semaphore but a semaphore with a bigger value (preferably equal to the number of reader threads). All of these threads can acquire the semaphore and release them when they are done. Also special care must be taken to to not starve the writer thread when many reader threads are active. This could be done in many ways - Just google for readers - writers problem and you will find out how you can do it.
I know this question has been asked before, But I am unable to figure out why my solution is not working for me. I have two threads even and odd, one prints even numbers and other prints odd numbers. When I start the threads I want the output to be in natural order of numbers like 0 1 2 3..etc. This is my code:-
[updated]
public class ThreadCommunication {
public static void main(String... args) throws InterruptedException
{
final ThreadCommunication obj = new ThreadCommunication();
Thread even = new Thread(){
#Override
public void run()
{
for(int i=0;i<10;i=i+2){
synchronized(obj){
System.out.println(i);
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
Thread odd = new Thread(){
#Override
public void run()
{
for(int i=1;i<10;i=i+2){
synchronized(obj){
System.out.println(i);
obj.notify();
}
}
}
};
even.start();
odd.start();
}
}
when I run the above code, sometimes it prints the numbers in natural order as expected but sometimes it prints in some other order for ex:
0
1
3
5
7
9
2
What am I doing wrong here?
Edit:
volatile static boolean isAlreadyWaiting = false;
Thread even = new Thread() {
#Override
public void run() {
synchronized (obj) {
for (int i = 0; i < 10; i = i + 2) {
System.out.println(i);
try {
if (!isAlreadyWaiting) {
isAlreadyWaiting = true;
obj.wait();
}
obj.notify();
isAlreadyWaiting=false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Thread odd = new Thread() {
#Override
public void run() {
synchronized (obj) {
for (int i = 1; i < 10; i = i + 2) {
System.out.println(i);
try {
if(isAlreadyWaiting){
obj.notify();
isAlreadyWaiting = false;
}
if (!isAlreadyWaiting) {
isAlreadyWaiting = true;
obj.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Check documentation
public class IllegalMonitorStateException extends RuntimeException
Thrown to indicate that a thread has attempted to wait on an object's
monitor or to notify other threads waiting on an object's monitor
without owning the specified monitor.
Monitor is owned by obj
So you should call
obj.wait();
and
obj.notify();
For more info on Ownership
This methods (wait or notify) should only be called by a thread that
is the owner of this object's monitor. A thread becomes the owner of
the object's monitor in one of three ways:
By executing a synchronized instance method of that object.
By executing the body of a synchronized statement that synchronizes
on the object.
For objects of type Class, by executing a synchronized static method
of that class.
Only one thread at a time can own an object's monitor.
#Pragnani Kinnera is right about the exception you're seeing. But if you want to alternate between even and odd, you'll need to move your second synchronized block into the loop. Otherwise, the notifying thread will hold the lock exclusively until the loop completes. (As opposed to the first thread, which yields its lock on each round.)
Thread odd = new Thread(){
#Override
public void run()
{
for(int i=1;i<10;i=i+2){
synchronized(obj){
System.out.println(i);
notify();
}
}
}
};
The first thread, however, should have the loop inside the synchronized block. If both threads release the lock, they both have an equal chance at reacquiring it. But if the first loop is inside the synchronized block, the second thread won't be able to reenter until the first has completed a full round and is waiting once again.
EDIT: This still won't work correctly, because there is no guarantee that the first thread won't reacquire the lock before the second thread does, per this quote from the documentation:
The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
You'll probably want to wake and notify from both threads to ensure they're in sync.
Here is your solution:
public class ThreadCommunication {
public static void main(String args[]) throws InterruptedException
{
final ThreadCommunication obj = new ThreadCommunication();
Thread even = new Thread("Even Thread"){
#Override
public void run()
{
for(int i=0;i<10;i=i+2){
System.out.println(i);
synchronized(obj){
obj.notify();
}
synchronized(obj){
try {
obj.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Thread odd = new Thread(){
#Override
public void run()
{
for(int i=1;i<10;i=i+2){
try {
synchronized(obj){
obj.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
synchronized(obj){
obj.notifyAll();
}
}
}
};
even.start();
odd.start();
}
}
As explained by #shmosel, your synchronized block should only contain code that need to be synchronized.
Create three threads and the main thread. Execute each thread as simultaneous tasks. Display information when exiting each thread.
I can run two threads with above exercise, but it hard to three threads. This is my program.
package Thread;
import java.util.concurrent.atomic.AtomicBoolean;
public class Test {
static AtomicBoolean lock = new AtomicBoolean(false);
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("New Thread: "
+ Thread.currentThread().toString());
for (int i = 5; i > 0; i--) {
synchronized (lock) {
if (lock.get()) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("First: " + i);
if (i == 1) {
System.out.println("Second exiting.");
}
lock.set(true);
lock.notify();
}
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("New Thread: "
+ Thread.currentThread().toString());
for (int i = 5; i > 0; i--) {
synchronized (lock) {
if (!lock.get()) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Second: " + i);
if (i == 1) {
System.out.println("Second exiting.");
}
lock.set(false);
lock.notify();
}
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main thread exiting.");
}
}
And the result:
Can you give me some methods or tips to resolve this problem. Thank you for your reply!
It's unclear what you want three threads to do. With two threads you have
one waiting on the bool to be false and one waiting on it to be true, right?
With three threads you need three states to wait on. You also need to be
really careful to set it up in a way so the state transitions happens exactly
in the right order and a set amount of times.
Either try to write that program, and tell us what goes wrong, or if you want
design help it might be good to tell us more about what you want to achieve in
the end.
A suggestion if you have a real multithreaded problem that needs to be solved
is to look into something like queues. They are really nice high level abstractions
that makes working with threads much nicer.
More likely though, you have some artificial task that needs to be solved, and then
you need to speak a bit about the constraints you have.
Read tutorials here about Thread synchronization in Java.
public class sync extends Thread {
public void run() {
synchronized (this) {
for (int i = 5; i > 0; i--) {
System.out.print("Thread Name :" + Thread.currentThread().getName() + i+"\n");
}
}
}
}
class demo {
public static void main(String args[]) {
sync obj1 =new sync();
sync obj2 =new sync();
sync obj3 =new sync();
obj1.setName("First");
obj2.setName("Second");
obj3.setName("Third");
obj1.start();
obj2.start();
obj3.start();
}
}
O/p:
Thread Name :First5
Thread Name :First4
Thread Name :First3
Thread Name :First2
Thread Name :First1
Thread Name :Second5
Thread Name :Second4
Thread Name :Second3
Thread Name :Second2
Thread Name :Second1
Thread Name :Third5
Thread Name :Third4
Thread Name :Third3
Thread Name :Third2
Thread Name :Third1
HOPE THIS HELPS :)
I am learning threading in java. As per the description of finally block in an Oracle tutorial:
Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.
So I tried to interrupt a thread in try catch block and check whether finally is executed in following class. But as per the output of the program, finally block is executed. Can someone explain what happened?
package com.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock{
public static void main(String[] args) throws InterruptedException {
MyThread lockT= new MyThread();
Thread t= new Thread(lockT);
t.setName("TempThread1");
t.start();
Thread.sleep(1000);
t.interrupt();
}
}
class MyThread implements Runnable {
Lock lock;
public MyThread() {
lock= new ReentrantLock();
}
#Override
public void run() {
try {
if(lock.tryLock()){
Thread.sleep(5000);
while (!Thread.currentThread().isInterrupted()) {
System.out.println("My thread name is "+ Thread.currentThread().getName());
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
System.out.println("finally ");
lock.unlock();
}
}
}
The rule here is saying: may not execute which does not mean it will not execute.
So basically the rule is saying: don't rely that the finally block will be executed, we don't provide such guarantees.
I know it's a old thread but I'd like to present a situation where the threads get interrupted and doesn't execute finally: Here is the sample code:
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.LockWork();
}public void LockWork() {
WithLock withLock = new WithLock();
Thread t1 = new Thread(() -> {
withLock.produce();
});
Thread t2 = new Thread(() -> {
withLock.consume();
});
ExecutorService service= Executors.newCachedThreadPool(new WithLockThreadFactory());
Future f1=service.submit(t1);
Future f2=service.submit(t2);
//f1.cancel(true);
try {
System.out.println("-------------------------------------sleeping now-------------------------------------");
Thread.sleep(3000);
System.out.println("-------------------------------------Intereputing Producer-------------------------------------");
f1.cancel(true);
service.shutdown();
Thread.sleep(1000);
System.out.println("is Producer done: "+f1.isDone());
service.awaitTermination(1, TimeUnit.DAYS);
System.out.println("is Consumer done: "+f2.isDone());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Ending Program");
}
now There is my Thread Factory:
public class WithLockThreadFactory implements ThreadFactory {
private int counter;
public WithLockThreadFactory() {
this.counter = 1;
}
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "WithLockThreadFactoryThread " + counter);
counter++;
return t;
}
now WithLock Class:
public class WithLock {
ReentrantLock lock = new ReentrantLock(true);
LinkedList<Integer> linkedList = new LinkedList<>();
Condition isEmpty = lock.newCondition();
Condition isFull = lock.newCondition();
int limit = 10;
volatile int interruptCounter = 0;
public void produce() {
System.out.println("WithLock.produce() Name: " + Thread.currentThread().getName());
try {
int value = 1;
while (true) {
lock.lockInterruptibly();
if (limit == linkedList.size()) {
System.out.println("acquiring lock in produce");
isEmpty.await(3000, TimeUnit.MILLISECONDS);
}
linkedList.add(value % limit);
System.out.println("value added to list: " + value % limit);
value++;
isFull.signal();
System.out.println("notifiedy lock in produce");
lock.unlock();
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("I was interupted Producer");
interruptCounter++;
System.out.println("interruptCounter value :" + interruptCounter);
} finally {
lock.unlock();
System.out.println("Finally Unlocked Producuer");
}
System.out.println("Ending things now: Producer");
}
public void consume() {
System.out.println("WithLock.consume() Name: " + Thread.currentThread().getName());
try {
while (true) {
lock.lockInterruptibly();
// no use as poll doesn't throw an exception if the queue is
// empty
if (linkedList.size() == 0) {
System.out.println("acquiring lock in consume");
isFull.await(3000, TimeUnit.MILLISECONDS);
if (interruptCounter > 2) {
break;
}
}
System.out.println("removing element from queue: " + linkedList.poll());
isEmpty.signal();
System.out.println("notifiedy lock in consume");
lock.unlock();
Thread.sleep(1000);
if (interruptCounter != 0) {
interruptCounter++;
}
}
} catch (InterruptedException e) {
System.out.println("I was Interupted Consumer");
} finally {
lock.unlock();
System.out.println("Finally Unlocked Consumer");
}
System.out.println("Ending things now: Consume");
}
}
and this is the output in the console:
-------------------------------------sleeping now-------------------------------------
WithLock.produce() Name: WithLockThreadFactoryThread 1
WithLock.consume() Name: WithLockThreadFactoryThread 2
value added to list: 1
notifiedy lock in produce
removing element from queue: 1
notifiedy lock in consume
acquiring lock in consume
value added to list: 2
notifiedy lock in produce
removing element from queue: 2
notifiedy lock in consume
acquiring lock in consume
value added to list: 3
notifiedy lock in produce
removing element from queue: 3
notifiedy lock in consume
-------------------------------------Intereputing Producer-------------------------------------
I was interupted Producer
interruptCounter value :1
acquiring lock in consume
is Producer done: true
removing element from queue: null
notifiedy lock in consume
acquiring lock in consume
Finally Unlocked Consumer
Ending things now: Consume
is Consumer done: true
Ending Program
This is something I found interesting and wanted to share. I tried it in JAVA8.
If the JVM exits...
Try System.exit() call...
First and foremost, Oracle's tutorials are descriptive and not normative. Your quote should by no means be taken as specification of behavior.
The thread can be interrupted while executing the finally block, in which case the said finally block may indeed fail to complete. This is, however, fully under your control and you can always write such a finally which is not susceptible to this happening.
Rest assured that the finally block will not be skipped over due to a regular InterruptedException occurring within its try block.
If a thread is being repeatedly stop()ped, however, it will be harder to ensure the finally block executes.