I was trying to print even and odd numbers by two threads repetitively using wait and notify. However, I have gone through all the implementations given in website. Though as a first time Multi threading developer I was trying to do it my self, but I could not get the desired result. Here I am pasting my code below: Could you please review and revert back with the corrections and explanations where I made the mistake.
package com.test.printEvenOdd;
public class PrintOddEvenNumbers {
public static void main(String[] args){
String s = new String("");
EvenThread t1= new EvenThread(s);
OddThread t2= new OddThread(s);
Thread th1 = new Thread(t1);
Thread th2 = new Thread(t2);
th1.start();
th2.start();
}
}
class EvenThread implements Runnable{
String s;
EvenThread(String s){
this.s= s;
}
#Override
public void run() {
synchronized(s){
for(int i=1;i<=10;i++){
if(i%2==0){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(i);
s.notify();
}
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
class OddThread implements Runnable{
String s;
OddThread(String s){
this.s= s;
}
#Override
public void run() {
synchronized(s){
for(int i=1;i<=10;i++){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(i%2==1){
System.out.println(i);
s.notify();
}
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Your problem is that you locking is too conservative/restrictive:
You put the lock around the whole loop; for both threads.
So, one thread gets into its loop; but quickly it can't progress. Because it would need that other thread to progress. But the second thread can't even start - because it can enter its loop at all!
In other words: in order to make progress; both threads need to be able to enter their respective loops; and make enough progress so that the other thread can do its next step.
Thats like building a room that only two person can exit together; but then you allow only one person to enter that room.
Welcome to multi-threaded programming; you just created your first dead-lock.
And for the record: when re-arranging the locks; make sure that you get the signaling right; so that wait/notify can work as supposed.
Finally: if you look carefully at your code; you will find that you duplicated a lot of code. That is always a bad idea. Instead: try to figure which parts are really different; and anything else ... should exist exactly once in your source code. So, as another exercise: when you re-arranged your code so that it does what it is supposed to do - try if you can refactor it, so that the amount of code duplication is minimized. I guarantee you, that will be an exercise worth spending your time on!
You should move the "wait()" inside the "if" block. Else thread will go in to wait without notifying the other waiting thread and both of them will be waiting.
if(i%2==0){
synchronized(s){
System.out.println(i);
try {
s.notify();
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
There are issues with the code. There is no need for sleep. As mentioned in previous response, you are synchronizing too eagerly which is unnecessary. There is no guarantee whether even thread will start first or odd thread will start first. It depends on whichever thread manages to acquire lock first. In the end, one thread will be waiting forever as the other thread would have come already come out and no one will notify after that. And any wait() code should handle spurious wakeup explained here
There are a number of issues with your initial code. See GhostCat's answer for explanations of them. In general, this sort of computation isn't great for multi threading since you are (apparently) wanting the numbers printed sequentially. But, given that desire and wanting to use 2 threads interleaving to do that, you could do it as follows. Note that there are still some problems with this solution. The thread depends on a different thread having executed to be able to reach it's own end condition which means that if you only created one for odd (or even) numbers, you'd go into an infinite loop.
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.IntPredicate;
public class Foo {
public static void main(String[] args) {
// an executor service will handle the thread pool and scheduling
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(new NumberPrintAndIncrement(i -> i % 2 != 0));
pool.submit(new NumberPrintAndIncrement(i -> i % 2 == 0));
// you want to shut down the pool when the threads are done
pool.shutdown();
}
}
final class NumberPrintAndIncrement implements Runnable {
// Need a shared lock for accessing and updating the current number
private static final Object LOCK = new Object();
// The number is shared between threads so it needs to be volatile
private static volatile int number = 1;
// Instance variable for letting a particular runnable know if it should
// print the number in it's current state
private final IntPredicate predicate;
NumberPrintAndIncrement(IntPredicate predicate) {
this.predicate = Objects.requireNonNull(predicate);
}
#Override
public void run() {
while (number < 10) {
// this could run at any point and any number of times, but
// that doesn't matter since it is just doing a quick check and
// a possible update. If the number doesn't satisfy the predicate,
// this will just be a no-op. Having a predicate means
// you don't have to rely on wait and notify to try and
// achieve interleaving the number output properly which
// is good due to the liveness problem Rajesh mentioned.
synchronized (LOCK) {
if (predicate.test(number)) {
System.out.println(number);
number++;
}
}
}
}
}
To understand what's happening a bit better, let's go through the steps happening in each Thread.
public class PrintOddEvenNumbers {
public static void main(String[] args){
String s = new String("");
EvenThread t1= new EvenThread(s);
OddThread t2= new OddThread(s);
Thread th1 = new Thread(t1);
Thread th2 = new Thread(t2);
th1.start();
th2.start();
}
}
class EvenThread implements Runnable{
String s;
EvenThread(String s){
this.s= s;
}
#Override
public void run() {
synchronized(s){
for(int i=1;i<=10;i++){
System.out.println("EvenThread i: " + i);
if(i%2==0){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(i);
System.out.println("EvenThread notify");
s.notify();
}
try {
System.out.println("EvenThread waiting..");
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
class OddThread implements Runnable{
String s;
OddThread(String s){
this.s= s;
}
#Override
public void run() {
synchronized(s){
for(int i=1;i<=10;i++){
System.out.println("OddThread i: " + i);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(i%2==1){
System.out.println(i);
System.out.println("OddThread notify");
s.notify();
}
try {
System.out.println("OddThread waiting..");
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
This will print:
EvenThread i: 1
EvenThread waiting..
OddThread i: 1
1
OddThread notify
OddThread waiting..
EvenThread i: 2
2
EvenThread notify
EvenThread waiting..
OddThread i: 2
OddThread waiting..
A simple explanation:
When OddThread reaches of i of 2, it waits for s to be released.
When EvenThread reaches i of 2, it also waits for s to be released.
You now have both threads waiting to be woken up (deadlock).
This happens because of the conditions that need to be met in order to wake the other waiting thread up using notify i.e. i%2==1 and i%2=0.
This isn't the only problem however, there are also some fundamental issues.
The usage of Threads in this particular case if it were in production is incorrect as you're trying to do sequential work anyway, so the overhead of creating Threads for each task adds unnecessary overhead.
There is no resource being shared, making synchornize redundant.
You expect that one Thread will get a hold of a lock before the other, this isn't how Thread's work - it can be either one that gets a hold of the lock first.
Related
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.
I am trying to simulate a parking lot entry system that contains 2 floors of 20 spaces and 2 entries and 2 exits. I am using Threads in Java, and I have tried to use thread.wait() and thread.sleep but they don't help in making a thread run after another thread is over.
This is what I have come up with so far:
ShardedDataThread.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class SharedDataThread extends Thread {
private SharedData mySharedData;
private String myThreadName;
public int L1 = 20;
public int L2 = 20;
//Setup the thread
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
SharedDataThread(String name, SharedData sharedstuff) {
super(name);
mySharedData=sharedstuff;
myThreadName=name;
}
//This is called when "start" is used in the calling method
public void run() {
while(true){
System.out.println("Entry or Exit?");
String input = null;
try {
input = br.readLine();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (input.equalsIgnoreCase("entry")) {
try {
// Acquire the lock using the acquireLock() method
// The thread will pause here on wait() until it gets a lock
mySharedData.acquireLock();
//use park method to occupy one space
this.park(); // Increment the number of reads
mySharedData.releaseLock();
}
catch(InterruptedException e) {
System.err.println("Failed to get lock when reading:"+e);
}
}
else {
try {
mySharedData.acquireLock();
System.out.println(myThreadName+" is writing");
exit(); // INCREMENT ONE SPOT
mySharedData.releaseLock(); // releases the lock
}
catch(InterruptedException e) {
System.err.println("Failed to get lock when writing:"+e);
}
}
System.out.println("L1 has : "+L1+" "+"L2 has: "+" "+L2);
}
//while ends
}
//State method
public void park() {
if (L1>0 && L1<=20){
L1= L1-1;
}
else if (L1==0 && L2<=20 && L2>0){
L2= L2-1;
}
else if (L1==0 && L2==0){
System.out.println("No Spaces Left");
}
}
public void exit() {
if (L1<20) {
L1 = L1 +1;
} else if (L2<20) {
L2 = L2+1;
}
}
public static void main(String[] args) throws InterruptedException {
SharedData mySharedData = new SharedData();
SharedDataThread myThread1 = new SharedDataThread("Entry1", mySharedData);
//SharedDataThread myThread2 = new SharedDataThread("Entry2", mySharedData);
//SharedDataThread myThread3 = new SharedDataThread("Exit1", mySharedData);
//SharedDataThread myThread4 = new SharedDataThread("Exit2", mySharedData);
// Now start the threads executing
myThread1.start();
//myThread1.join();
//myThread2.start();
//myThread2.join();
//myThread3.start();
//myThread3.join();
//myThread4.wait();
}
}
SharedData.java
public class SharedData {
private boolean accessing=false; // true a thread has a lock, false otherwise
// attempt to acquire a lock
public synchronized void acquireLock() throws InterruptedException{
Thread me = Thread.currentThread();
while (accessing) {
wait();
}
accessing = true;
}
// Releases a lock to when a thread is finished
public synchronized void releaseLock() {
//release the lock and tell everyone
accessing = false;
notifyAll();
Thread me = Thread.currentThread(); // get a ref to the current thread
}
}
This never makes any sense:
myThread1.start();
myThread1.join();
It never makes any sense to start a thread and then immediately wait for it to finish. The entire point of having threads is that different threads can be doing different things at the same time.
If there isn't anything else that the caller wants to do while myThread1 is running, then there is no reason to create myThread1. The caller should just do whatever it is that myThread1 would have done at that point.
Don't use threads to model objects in a simulation. Use threads to do work. Usually, that means, use a thread pool such as java.util.concurrent.ThreadPoolExecutor to perform tasks.
If you want your simulation to run in real time, don't use threads that sleep(). Use a scheduler such as java.util.concurrent.ScheduledThreadPoolExecutor to perform delayed tasks.
You're thinking about the problem wrong. Don't think about waiting for a thread to do something after a thread is done. Think about doing something after some work is done. That means that the work has to be waitable.
I have written some Java code, which will call a C interrupt handler.
In Java thread A, I use waitFor() to wait the interrupt coming and then execute reboot.
In Java thread B, I will loop printing a counter value and sleep several milliseconds.
And I hope when I detect the interrupt, and then stop the printing in thread B at once, but failed. In fact, the system detects the interrupt in time, but the printing continues for maybe 10 seconds and then reboot. Note: reboot occurs maybe 11 seconds after the interrupt(press a button), the hardware is not fast.
Below is my code, any suggestion? Thanks!
import java.io.IOException;
class ThreadTesterA implements Runnable
{
private int counter;
private String cmds[] = new String[1];
private Process pcs;
#Override
public void run()
{
cmds[0] = "./gpio-interrupt";
try {
pcs = Runtime.getRuntime().exec(cmds);
if(pcs.waitFor() != 0) {
System.out.println("error");
} else {
ThreadTesterB.setClosed(true);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ThreadTesterB implements Runnable
{
private int i;
private static boolean closed=false;
public static void setClosed(boolean closed)
{
closed = closed;
}
#Override
public void run()
{
// replace it with what you need to do
while (!closed) {
System.out.println("i = " + i);
i++;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println();
}
}
public class ThreadTester
{
public static void main(String[] args) throws InterruptedException
{
Thread t1 = new Thread(new ThreadTesterA());
Thread t2 = new Thread(new ThreadTesterB());
t1.start();
t1.setPriority(Thread.MAX_PRIORITY);
//t1.join(); // wait t1 to be finished
t2.start();
//t2.join();
}
}
You're writing and reading a boolean variable (closed) from 2 different threads without any kind of synchronization. There is thus no guarantee that what you wrote in one thread is visible in the other thread. You need to either
make the boolean variable volatile
access the boolean variable (writing and reading) using blocks or methods synchronized on the same lock
use an AtomicBoolean instead of a boolean
I would use the third solution.
I have a code in here which is being used to explain how the semaphore works.. No matter How hard I try I am not understanding the line below and there by how to code semaphore is invoked.
Basically the code tries to simulate many connects being made...
import java.util.concurrent.Semaphore;
public class Connection {
private static Connection instance = new Connection();
private Semaphore sem = new Semaphore(10, true);
private int connections = 0;
private Connection() {
}
public static Connection getInstance() {
return instance;
}
public void connect() {
try {
sem.acquire();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
doConnect();
} finally {
sem.release();
}
}
public void doConnect() {
synchronized (this) {
connections++;
System.out.println("Current connections: " + connections);
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (this) {
connections--;
}
}
}
Main class file..
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class App {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
for(int i=0; i < 200; i++) {
executor.submit(new Runnable() {
public void run() {
Connection.getInstance().connect();
}
});
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.DAYS);
}
}
I am not understanding the run part
public void run() {
Connection.getInstance().connect();
}
How can we call a connect method from the above? in my judgement connections output should always be one as new threads are being called. surprisingly but that never happens.
I'll try to explain what's happening there. This code below is being run in each separate thread since you're submitting it to a thread pool:
public void run() {
Connection.getInstance().connect();
}
Connection.getInstance() here returns a singleton (an single instance of an object Connection which is shared among threads, more: What is an efficient way to implement a singleton pattern in Java?). This singleton in it's turn contains a semaphore which is also single and is shared among the threads. So the whole purpose of this technique in this case is to share a semaphore between multiple threads.
What happens in connect():
public void connect() {
try {
// this acquires a single permit for a shared semaphore,
// so no more than 10 threads (the result of new Semaphore(10, true))
// will enter the critical section below simultaneously
sem.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
// the critical section, at this point there will be 10 threads at max
// this is the purpose of the semaphore
doConnect();
} finally {
// returns the permit acquired, so that a one more thread may
// enter the critical section
sem.release();
}
}
Semaphore is used to acquire lock , and execute some code then finally release the lock.
In your code also same thing is happening.
sem.acquire(); will acquire a lock .
doConnect(); // write your code here .
sem.release(); release the lock .
For more details refer this .
I have a thread that is running and performing a task repeatedly. I've implemented a counter to show me the iterations of the task performed by the thread. Every now and then I see that the counter is stuck somewhere and it's not increasing anymore. I don't receive any error or exceptions. The application runs but it looks like the thread just stopped without me asking it.
I will add some code to show the thread execution:
notice the int "c" - thats the counter for iterations.
public void check() {
Thread check = new Thread() {
public void run() {
for (;;) {
EventQueue.invokeLater(new Runnable() {
public void run() {
// Update GUI here on EventQueue.
try {
Task.readTasks();
} catch (InvalidFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (NoteInfo == null || NoteInfo == "") {
btnViewNote.setEnabled(false);
} else {
btnViewNote.setEnabled(true);
}
textField.setText(Task.printNextTask);
c++;
lblCycle.setText("Cycle: " + c);
}
});
try {
Thread.sleep(5000);
// Task.initializeIt();
} catch (InterruptedException ie) {
break;
}
if (killcheck)
break;
}
}
};
check.start();
}
public static void stopChecking() {
killcheck = true;
progressBar.setValue(0);
textArea.setText("");
textField.setText("");
c = 0;
lblCycle.setText("Cycle: " + c);
}
The check thread gets interrupted by another thread. Print the stack trace in the catch block and verify it.
try {
Thread.sleep(5000);
// Task.initializeIt();
} catch (InterruptedException ie) {
// break; // just ignore it
}
I don't see the definitions of killcheck or c but it is possible that these have not been marked as volatile?
If multiple threads are reading and writing a shared value then there must be some sort of synchronization otherwise they could be dealing with stale values. You can either use one of the atomic classes such as AtomicBoolean or AtomicInteger, use the synchronized keyword, or mark the variable as volatile. All three would allow the main thread and the inner thread to see each other's changes to the shared fields.
volatile int c;
volatile boolean killcheck;
For posterity, here's how you use the atomic classes:
final AtomicInteger c = new AtomicInteger();
final AtomicBoolean killcheck = new AtomicBoolean();
...
c.incrementAndGet();
...
if (killcheck)
break;
...
killcheck.set(true);
...
c.set(0);