I created two separate threads one for writing into a list and second for removing from the list.
package com.produ.consu;
public class Test {
public static void main(String[] args) {
Operations operations = new Operations();
Runnable r1 = new ThreadsClass(operations);
Runnable r2 = new ThreadsClass(operations);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.setName("READ");
t2.setName("WRITE");
t1.start();
t2.start();
}
}
Above is Test class where I created threads.
package com.produ.consu;
public class ThreadsClass implements Runnable {
Operations operations;
ThreadsClass(Operations operations){
this.operations=operations;
}
#Override
public void run() {
// TODO Auto-generated method stub
if(Thread.currentThread().getName().equals("WRITE")) {
operations.writeList();
}
else {
operations.readList();
}
}
}
Above is class calling synchronized methods based on the thread name:
import java.util.ArrayList;
import java.util.List;
public class Operations {
List<Integer> list=null;
int count=0;
boolean flag;
Operations(){
list=new ArrayList<>();
flag=true;
}
public synchronized void writeList() {
// TODO Auto-generated method stub
while(true) {
if(flag) {
count++;
list.add(count);
System.out.println("inise if block...."+Thread.currentThread().getName());
System.out.println(list);
flag=false;
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
notify();
}
}
}
public synchronized void readList() {
// TODO Auto-generated method stub
while(true) {
if(!flag) {
Integer i = list.remove(0);
System.out.println(i+"..removed at index by"+Thread.currentThread().getName());
flag=true;
notify();
}
else {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Above is where I mentioned functionality.
So write thread hast to write element to list and wait until it is removed by the second thread.
Once removed second should notify 1st and wait for until element inserted.
But getting...
inise if block....WRITE [1]
Not even removed and it has to be a continuous process.
Give me suggestions on given code.
You should wait() inside the else block also, otherwise the while will continue to run if the if is not satisfied and the other thread won't get a chance to execute.
After the read/write operation is performed the thread should call notify to wake up the other thread and itself should go in the waiting state.
public synchronized void writeList() {
while (true) {
if (flag) {
count++;
list.add(count);
System.out.println("inise if block...." + Thread.currentThread().getName());
System.out.println(list);
flag = false;
try {
notify(); //notify the read thread that write is complete
wait(); // go into the waiting state so that no further write is done until the current element is removed by the read thread.
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
wait(); //wait in else, otherwise while will run endlessly
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public synchronized void readList() {
while (true) {
System.out.println("in read");
if (!flag) {
Integer i = list.remove(0);
System.out.println(i + "..removed at index by" + Thread.currentThread().getName());
flag = true;
try {
notify(); //notify write thread that read is complete
wait(); //go into wait until new element is inserted
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
wait(); //wait in else otherwise while runs endlessly
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You should replace the method synchronization with more granular synchronization: wrap the operations that access the list and update count with a synchronized block.
Alternatively, use a linked blocking queue to pass “messages” between threads (or, in more advanced scenarios, a messaging solution such as Akka, Kafka, zeromq, or other similar solutions)
Since you only add one elemet at a time you could also use a Exchanger.
Take a look at the Java concurrent package.
import java.io.IOException;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Foo {
public static void main(String[] args) throws IOException, InterruptedException {
final Exchanger<Integer> exchanger = new Exchanger<>();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
// producer
int count = 0;
while (!Thread.currentThread().isInterrupted()) {
try {
exchanger.exchange(count++);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
executorService.execute(() -> {
// reader
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("consume " + exchanger.exchange(null));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
System.in.read();
executorService.shutdownNow();
executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("Shut down");
}
}
Related
I was looking at a producer-consumer example with wait and notify, even though it works some times it gives exception. Not able to figure out where the problem is.
Exception in thread "Thread-5" java.util.NoSuchElementException at
java.util.LinkedList.removeFirst(Unknown Source) at com.bhatsac.workshop.producerconsumer.ProdNConsumer.consumer(ProdNConsumer.java:55)
at com.bhatsac.workshop.producerconsumer.ProdConsumerInvoker.lambda$5 (ProdConsumerInvoker.java:35)
at java.lang.Thread.run(Unknown Source)
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;
public class ProdNConsumer {
LinkedList<Integer> list = new LinkedList<Integer>();
private int LIMIT = 1;
private volatile boolean shutdown = false;
private AtomicInteger counter=new AtomicInteger(0);
private Object lock=new Object();
public void produce() {
while (true) {
synchronized(lock){
System.out.println("In producer :)"+ list.size());
if(this.list.size()==this.LIMIT){
try {
System.out.println("In waiting state producer");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Produced by thread= "+ Thread.currentThread().getName());
list.add(counter.getAndIncrement());
System.out.println("Going to sleep for a while");
lock.notifyAll();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void consumer() {
while (true) {
synchronized(lock){
System.out.println("In consumer :)");
if(list.size()==0){
try {
System.out.println("In waiting state consumer");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("consumed by thread="+ Thread.currentThread().getName());
list.removeFirst();
lock.notifyAll();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class ProdConsumerInvoker {
public static void main(String[] args) {
ProdNConsumer pc= new ProdNConsumer();
Thread tc1=new Thread(()->{pc.consumer();});
new Thread(()->{pc.produce();}).start();
new Thread(()->{pc.produce();}).start();
Thread tp1=new Thread(()->{pc.produce();});
new Thread(()->{pc.consumer();}).start();
new Thread(()->{pc.consumer();}).start();
tp1.start();
tc1.start();
}
}
Your producer and consumer threads are using the same lock. When a consumer wakes up and consumes an element, it calls lock.notifyAll(), which will wake up all consumers and producers waiting on it. Another consumer wakes up thinking there are items in the list, but it removes the first item from an empty list, causing the exception.
In the consumer, instead of if(list.size()==0), use while(list.size()==0). Similar reasoning applies to the producer as well. Just because the thread woke up doesn't mean that the condition it is waiting on is true. It only means that before the thread woke up the condition was true. It must check it again.
I am exploring java.util.concurrent.*
Calculating the square and waiting using Thread.sleep(5000) , the program works as expected, but never terminates.
The red square in eclipse is "ON", that we usually use to terminate the program.
Can you please help in understanding why the program doesn't terminate on completion??
public static void main(String[] args) throws InterruptedException, ExecutionException {
// TODO Auto-generated method stub
try {
SquareCalculator sqC = new SquareCalculator();
sqC.display(1);
Future<Integer> result = sqC.calculate(5);
while(!result.isDone())
{
System.out.println("Waiting for the calculation");
Thread.sleep(1000);
//result.cancel(true);
}
Integer square = result.get();
System.out.println(square);
}catch(Exception e)
{
e.printStackTrace();
System.out.println("Calclulation was interrupted");
}
}
public class SquareCalculator {
private ExecutorService ex = Executors.newSingleThreadExecutor();
public void display(int i) {
// TODO Auto-generated method stub
System.out.println(i);
}
public Future<Integer> calculate(Integer inp)
{
try {
System.out.println("Before sending request");
Future<Integer> res = ex.submit(()->{
Thread.sleep(5000);
return inp*inp;
});
System.out.println("Request sent to caluclate and waiting for the result");
return res;
}catch(Exception e)
{
System.out.println("calculation was interrupted");
return null;
}
//return ex.submit(()->squareing(inp));
}
}
OUTPUT
1
Before sending request
Request sent to caluclate and waiting for the result
Waiting for the calculation
Waiting for the calculation
Waiting for the calculation
Waiting for the calculation
Waiting for the calculation
25
You need to refactor your code and return the object instead of Future. You should also shutdown executor when you are done.
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class SquareCalculator {
private ExecutorService ex = Executors.newSingleThreadExecutor();
public void display(int i) {
// TODO Auto-generated method stub
System.out.println(i);
}
public Integer calculate(Integer inp) {
Integer result;
try {
System.out.println("Before sending request");
Future<Integer> res = ex.submit(() -> {
Thread.sleep(5000);
return inp * inp;
});
System.out.println("Request sent to caluclate and waiting for the result");
result = res.get();
ex.shutdown();
return result;
} catch (Exception e) {
System.out.println("calculation was interrupted");
return null;
}
//return ex.submit(()->squareing(inp));
}
public static void main(String[] args) throws InterruptedException,
ExecutionException {
// TODO Auto-generated method stub
try {
SquareCalculator sqC = new SquareCalculator();
sqC.display(1);
Integer result = sqC.calculate(5);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Calclulation was interrupted");
}
}
}
I would rather create an executor outside the Calculator class and the pass it in the constructor.
This way the application has control over the ExecutorService and shut it down when necessary.
Also, if you create more then one instance of a calculator, all instance use the same executor service, so you can control how many instance can run in parallel.
Blocking in the calculate method works, but defeats the purpose of using another thread to make an async calculation.
public static void main(String[] args) {
// The executor is created by the application and then
// passed to the calculator
ExecutorService executor = Executors.newCachedThreadPool();
SquareCalculator calculator = new SquareCalculator(executor);
// calculate does not block
Future<Integer> calculate = calculator.calculate(12);
try {
while(true) {
try {
// wait a limited amount of time for the computation to complete
Integer result = calculate.get(1, TimeUnit.SECONDS);
System.out.println(result);
if(calculate.isDone()) {
// If the computation was either complete or cancelled just quit
break;
}
} catch (TimeoutException e) {
// We expect timeouts so we don't quit the loop for them
System.out.println("Waiting for result");
}
}
} catch (InterruptedException | ExecutionException e) {
// If there was an error or the computation was interrupted just quit.
e.printStackTrace();
}
// Shut down the executor so we do not leak pools.
executor.shutdown();
}
public class SquareCalculator {
private ExecutorService ex;
public SquareCalculator(ExecutorService ex) {
super();
this.ex = ex;
}
public void display(int i) {
System.out.println(i);
}
public Future<Integer> calculate(Integer inp) {
try {
System.out.println("Before sending request");
Future<Integer> res = ex.submit(() -> {
Thread.sleep(5000);
return inp * inp;
});
System.out.println("Request sent to caluclate and waiting for the result");
return res;
} catch (Exception e) {
System.out.println("calculation was interrupted");
return null;
}
}
}
If you want the VM to shut down, call System.exit(). Yes, the VM can automatically close without calling that method as well; it does this if ALL still 'live' threads have the 'daemon' flag up (the Thread class has a .setDaemon method for this purpose), but that's bad code style. If the point is to shut down, then shut down (with System.exit).
Specifically here, the threads created by Executors.newSingleThreadExecutor(); aren't marked as daemon threads. You can fix that by supplying a thread creator to the call.
But, really, don't. Use System.exit.
This question already has answers here:
Java InputStream blocking read
(7 answers)
Closed 8 years ago.
I have written a sample program to illustrate the working with pipe is thread. I have created 2 threads.
Thread1 is sending "Hi this is thread1" and call wait() for thread 2 to complete.
Thread2 is printing the message sent by thread1 and also will also append into a string buffer, then once the entire message is received, thread2 will print the contents of string buffer and will call notify. Now after calling wait() and notify both threads tend to be in deadlock
Strangely, thread2 prints the message one but does not print the contents of string buffer.
package com.tuto.MultiThreading;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipeExample {
public static void main(String[] args) throws IOException, InterruptedException {
final Object obj=new Object();
final PipedOutputStream pipeoutstream=new PipedOutputStream ();
final PipedInputStream pipeinputstream=new PipedInputStream(pipeoutstream);
Thread thread1= new Thread(new Runnable()
{
public void run() {
try {
pipeoutstream.write("Hello I am thread1".getBytes());
synchronized (obj)
{
obj.wait();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try {
pipeoutstream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
try {
int data = pipeinputstream.read();
StringBuffer sb=new StringBuffer();
while(data != -1){
System.out.print((char) data);
sb.append((char)data);
data = pipeinputstream.read();
}
System.out.println();
System.out.println(sb.toString());
synchronized (obj) {
obj.notify();
}
} catch (IOException e) {
e.printStackTrace();
}
finally
{
try {
pipeinputstream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.exit(1);
}
}
OUTPUT::
Hello I am thread1
Updated Resolution:
package com.tuto.MultiThreading;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipeExample {
public static void main(String[] args) throws IOException, InterruptedException {
final Object obj=new Object();
final PipedOutputStream pipeoutstream=new PipedOutputStream ();
final PipedInputStream pipeinputstream=new PipedInputStream(pipeoutstream);
Thread thread1= new Thread(new Runnable()
{
public void run() {
try {
pipeoutstream.write("Hello I am thread1".getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try {
pipeoutstream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (obj)
{
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
try {
int data = pipeinputstream.read();
StringBuffer sb=new StringBuffer();
while(data != -1){
System.out.print((char) data);
sb.append((char)data);
data = pipeinputstream.read();
}
System.out.println();
System.out.println(sb.toString());
synchronized (obj) {
obj.notify();
}
} catch (IOException e) {
e.printStackTrace();
}
finally
{
try {
pipeinputstream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.exit(1);
}
}
Now i am a bit more confused. I just moved wait() from try catch to finally. How did it affect the blocking of Pipestream?
The problem is that
data = pipeinputstream.read();
in thread 2 is a blocking call. From the javadoc of PipedInputStream#read()
This method blocks until input data is available, the end of the
stream is detected, or an exception is thrown.
Thread 2 keeps waiting until one of those things happen. Since none of them will ever happen, the thread will not be able to notify the other.
This is not deadlock.
Note that even if that call unblocked and returned -1, thread 2 could still execute its notify before your thread 1 called wait. In which case, thread 1 would be a in a constant waiting state and your program would not terminate.
I am trying to do it using two threads like below. Can someone point the obvious mistake I am doing here?
public class OddEven {
public static boolean available = false;
public static Queue<Integer> queue = new LinkedList<Integer>();
static Thread threadEven = new Thread() {
#Override
public void run() {
printEven();
}
public synchronized void printEven() {
while (!available) {
try {
wait();
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
System.out.println(queue.remove());
available = false;
notifyAll();
}
};
static Thread threadOdd = new Thread() {
#Override
public void run() {
printOdd();
}
public synchronized void printOdd () {
while (available) {
try {
wait();
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
System.out.println(queue.remove());
available = true;
notifyAll();
}
};
public static void main(String[] args) {
int n = 20;
for (int i = 1; i < n; i++) {
queue.add(i);
}
threadOdd.start();
threadEven.start();
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
threadOdd.join();
threadEven.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
But this program is only printing 1 and quitting. After printing 1 the available should be true and printEven should wake up, print and set available to false. I don't understand what is going wrong here? I saw other solutions but want to know why my solution is not working.
Putting synchronized on an instance method means that the thread calling that method has to acquire the lock on that instance; public void synchronized printOdd() is syntax sugar for
public void printOdd() {
synchronized(this) {
...
}
}
where this is different for each instance, since ThreadOdd and threadEven are two different objects and each one uses its own lock. The methods notifyAll and wait are called on the object that is being used as the lock. When one thread waits it never gets notified because the notification only applies to other threads waiting on the same lock as the notifying thread.
Is there any neat solution of knowing when a thread has been put into wait status? I am putting threads to wait and I notify them when i need it. But sometimes I want to know if a thread is currently waiting, and if so, I have to do something else.
I could probably set a flag myself to true/false. But I can't imagine there is a better way to do this?
The method getState() of a thread returns a Thread.State which can be:
NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING or TERMINATED
See Thread.State.
Have you looked at Thread.getState?
Check
public Thread.State getState()
Thread.State.WAITING
Thread.State: Differences between BLOCKED vs WAITING
You can have all info that you want using the ThreadMXBean.
Try this code:
package com.secutix.gui.seatmap;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
public class ThreadStatus {
private static final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
buildAndLaunchThread(i);
}
Thread t = new Thread(){
#Override
public void run() {
while(true){
printThreadStatus();
try {
sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
t.setName("detector");
t.start();
}
protected static void printThreadStatus() {
ThreadInfo[] infos = mbean.dumpAllThreads(true, true);
for (ThreadInfo threadInfo : infos) {
System.out.println(threadInfo.getThreadName() + " state = " + threadInfo.getThreadState());
}
}
private static void buildAndLaunchThread(int i) {
Thread t1 = new Thread(){
#Override
public void run() {
while(true){
try {
sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
t1.setName("t" + i);
t1.start();
}
}