I am trying to implement threads where one thread generates a random number while another thread waits once it generates random number it should notify and wait for the other thread to do the same. I am getting illegal monitor state exception, please help me out and point out my mistake
class Dice
{
int diceValue;
public Dice()
{
this.diceValue=0;
}
}
public class DiceGame implements Runnable
{
Dice d;
public DiceGame()
{
this.d=new Dice();
}
public void run()
{
if(Thread.currentThread().getName().equals("Player 1"))
{
Random rg=new Random();
for(int i=0;i<6;i++)
{
synchronized(d)
{
d.diceValue=rg.nextInt(6);
System.out.println(Thread.currentThread().getName()+" dice Value is "+d.diceValue);
d.notifyAll();
try
{
d.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
else if(Thread.currentThread().getName().equals("Player 2"))
{
Random rg=new Random();
for(int i=0;i<6;i++)
{
synchronized(d)
{
try
{
d.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
d.diceValue=rg.nextInt(6);
System.out.println(Thread.currentThread().getName()+"dice Value is ");
d.notifyAll();
}
}
}
}
public static void main(String []args)
{
DiceGame dg=new DiceGame();
Thread tr1=new Thread(dg);
Thread tr2=new Thread(dg);
tr1.setName("Player 1");
tr2.setName("Player 2");
tr1.start();
tr2.start();
}
}
synchronized(d)
{
try
{
d.wait();
Any time you see an unconditional call to wait, you know there's a bug right there. Before you wait, you have to make sure the thing you're waiting for didn't already happen. That's the reason you entered synchronized a block, right?
The whole point of the wait/notify mechanism is that you can atomically release a lock and await notification. That can't possibly work if you don't check the predicate (the thing that you're waiting for) before calling wait.
Here synchronized block is necessary to hold the monitor when calling wait.
Right, because unless you're inside a synchronized block, there's no way you can tell whether the thing you're waiting for has already happened or not. And since you must check whether it's already happened before you wait for it, you can only call wait from inside a synchronized block. But you didn't check! You understand the requirement but not its rationale, so you formally met it, but still managed to create the very problem the requirement is designed to prevent!
I guess, the problem is that you are notifying every other thread before waiting youself.
d.notifyAll();
try
{
d.wait();
}
Refer to this post: https://stackoverflow.com/a/828341/5602214
Your code could be improved in several ways, but with a few little hacks it can work:
class Dice
{
int diceValue;
public Dice()
{
this.diceValue=0;
}
}
public class DiceGame implements Runnable
{
Dice d;
public DiceGame()
{
this.d=new Dice();
}
#Override
public void run()
{
if(Thread.currentThread().getName().equals("Player 1"))
{
final Random rg=new Random();
for(int i=0;i<6;i++)
{
synchronized(d)
{
d.diceValue=rg.nextInt(6);
System.out.println(Thread.currentThread().getName()+" dice Value is "+d.diceValue);
d.notifyAll();
try
{
d.wait();
}
catch (final InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
else if(Thread.currentThread().getName().equals("Player 2"))
{
final Random rg=new Random();
for(int i=0;i<6;i++)
{
synchronized(d)
{
try
{
d.wait();
}
catch (final InterruptedException e)
{
e.printStackTrace();
}
d.diceValue=rg.nextInt(6);
System.out.println(Thread.currentThread().getName()+" dice Value is "+d.diceValue);
d.notifyAll();
}
}
}
}
public static void main(final String []args) throws InterruptedException
{
final DiceGame dg=new DiceGame();
final Thread tr1=new Thread(dg);
final Thread tr2=new Thread(dg);
tr1.setName("Player 1");
tr2.setName("Player 2");
tr2.start();
Thread.sleep(100);
tr1.start();
}
}
I got no illegalMonitorstate exception, but the first thread get locked up forever. Basically the problem is that the first thread rolls the dice, and calls d.notifyAll before actually the 2nd thread could start and waiting for the dice. This is naively solved by first starting thread 2 then waiting a bit and start thread 1.
You might also consider:
using the Java convention for braces { }
rg.nextInt gives values between 0..5, not 1..6
it is bad idea to make the thread code work differently depending on the name of the thread. In OOP different behavior is expressed with descendant classes instead.
I guess you're wishing for an universal solution for rolling the dice with multiple players. This problem is not necessarily a problem which requires concurrent programming, since rolling the dice goes serially amongst players. You can of course have the players as Threads, but only one Thread will be active at any point of time. In case of using Threads, you shall implement your own scheduling logic which ensures consistent one-after-another scheduling of threads. Using a monitor (e.g. synchornize(d)) does not offer any guarantee of the ordering, it is only built to guarantee that up to one thread can access to the dice at any point in time.
A solution with any number of players but no threads (this is not a concurrency problem after all) shows this behavior:
import java.util.Random;
class Dice {
private final Random rg=new Random();
private int diceValue=1;
public void roll() {
diceValue=rg.nextInt(6)+1;
}
#Override
public String toString() {
return "value="+diceValue;
}
}
public class Player extends Thread {
Dice dice;
int rollsLeft=6;
public Player(final Dice dice) {
this.dice=dice;
}
#Override
public void run() {
while (rollsLeft>0) {
synchronized(dice) {
// dice obtained
dice.roll();
System.out.println(Thread.currentThread().getName()+" rolled "+dice);
}
// dice released
rollsLeft--;
// just wait a little to make it slower and let other threads to join
try {
Thread.sleep(100);
} catch (final InterruptedException e) {
// ignore
}
}
}
public static void main(final String []args) throws InterruptedException {
final Dice dice=new Dice();
final Player player1=new Player(dice);
final Player player2=new Player(dice);
player1.start();
player2.start();
}
}
Which gives:
Thread-0 rolled value=1
Thread-1 rolled value=6
Thread-0 rolled value=2
Thread-0 rolled value=4
Thread-1 rolled value=2
etc...
As you can see, the order (i.e. player1, player2, player1, player2) is not guaranteed.
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
class Dice {
private final Random rg=new Random();
private int diceValue=1;
public void roll() {
diceValue=rg.nextInt(6)+1;
}
#Override
public String toString() {
return "value="+diceValue;
}
}
public class Player {
Dice dice;
String player;
public Player(final Dice dice,final String player) {
this.dice=dice;
this.player=player;
}
public void roll() {
dice.roll();
System.out.println(player+" rolled "+dice);
}
public static void main(final String []args) throws InterruptedException {
final Dice dice=new Dice();
final List<Player> players=new ArrayList<Player>();
players.add(new Player(dice,"Ann"));
players.add(new Player(dice,"Ben"));
players.add(new Player(dice,"Cecil"));
players.add(new Player(dice,"Denise"));
for (int rounds=0;rounds<6;rounds++) {
System.out.println("---");
for (final Player player:players) {
player.roll();
}
}
}
}
Which gives you the expected output, i.e. Ann, Ben, Cecil, Denise has 6 rounds of rolling the dice.
Related
I am trying to print numbers from 1 to 10 using three threads. thread 1 prints 1, 2 prints 2, 3 prints 3, 4 is printed by thread 1 again and so on.
I have created a shared printer resource that helps those threads to print number. But I am getting confused as how can i make the number to be visible by all threads.
The problem is eachthread is seeing their own copy of number while I need the same number to be shared by all threads.
I am trying to create this example for learning purposes. I have seen other pages on SO that had same kind of problem but I am not able to get the concept.
Any help is appreciated.
how is this example diffrent from what I am doing?
Printing Even and Odd using two Threads in Java
public class PrintAlternateNumber {
public static void main(String args[]) {
SharedPrinter printer = new SharedPrinter();
Thread t1 = new Thread(new myRunnable2(printer,10,1),"1");
Thread t2 = new Thread(new myRunnable2(printer,10,2),"2");
Thread t3 = new Thread(new myRunnable2(printer,10,3),"3");
t1.start();
t2.start();
t3.start();
}
}
class myRunnable2 implements Runnable {
int max;
SharedPrinter printer;
int threadNumber;
int number=1;
myRunnable2(SharedPrinter printer,int max,int threadNumber) {
this.max=max;
this.printer=printer;
this.threadNumber=threadNumber;
}
#Override
public void run() {
System.out.println(" The thread that just entered run "+ Thread.currentThread().getName());
for(int i =1;i<max;i++){
try {
printer.print(i,threadNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class SharedPrinter {
boolean canPrintFlag=false;
public synchronized void print(int number,int threadNumber) throws InterruptedException{
if(number%3==threadNumber) {
canPrintFlag=true;
}
while(!canPrintFlag)
{
System.out.println(Thread.currentThread().getName() + " is waiting as it cannot print " + number);
wait();
}
System.out.println(Thread.currentThread().getName()+" printed "+number);
canPrintFlag=false;
notifyAll();
}
}
//output
//The thread that just entered run 2
// The thread that just entered run 3
//The thread that just entered run 1
//3 is waiting as it cannot print 1
//1 printed 1
//1 is waiting as it cannot print 2
//3 is waiting as it cannot print 1
//2 is waiting as it cannot print 1
Technique second
it is still incomplete but I am close
output
0printed by0
2printed by2
1printed by1
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
class AlternateNumber {
public static void main(String args[]) {
printerHell ph = new printerHell();
BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10);
for(int i=0;i<10;i++)
{
queue.add(i);
}
Thread t1 = new Thread(new myRunnableHell(queue,0,ph),"0");
Thread t2 = new Thread(new myRunnableHell(queue,1,ph),"1");
Thread t3 = new Thread(new myRunnableHell(queue,2,ph),"2");
t1.start();
t2.start();
t3.start();
}
}
class myRunnableHell implements Runnable {
BlockingQueue<Integer> queue;
int threadNumber;
printerHell ph;
myRunnableHell(BlockingQueue<Integer> queue, int threadNumber,printerHell ph) {
this.queue=queue;
this.threadNumber=threadNumber;
this.ph=ph;
};
int currentNumber;
#Override
public void run() {
for(int i=0;i<queue.size();i++)
{
currentNumber=queue.remove();
if(threadNumber%3==currentNumber)
{
ph.print(currentNumber);
}
}
}
}
class printerHell {
public synchronized void print(int Number)
{
System.out.println(Number + "printed by" + Thread.currentThread().getName());
}
}
Please see my solution here..
Using simple wait/notify
https://stackoverflow.com/a/31668619/1044396
Using cyclic barriers:
https://stackoverflow.com/a/23752952/1044396
For your query on 'How different it is from even/odd thread problem.
--> it is almost same ... instead of maintaining two states have one more state to call the third thread, so I believe,this can be extended any number of threads.
EDIT:
You may view this approach when you want to have 'n' number of threads to do the work sequentially.(Instead of having different classes t1,t2,t3 etc)
https://codereview.stackexchange.com/a/98305/78940
EDIT2:
Copying the code here again for the above solution
I tried to solve using a single class 'Thrd' which gets initialized with its starting number.
ThreadConfig class which as size of total number of threads you want to create.
State class which maintains the state of the previous thread.(to maintain ordering)
Here you go..(please review and let me know your views)
EDIT:
How it works -->
when a thread Tx gets a chance to execute.. it will set state variable's state with x. So a next thread(Tx+1) waiting , will get a chance once state gets updated. This way you can maintain the ordering of threads.
I hope i am able to explain the code. Please run it and see or let me know for any specific queries on the below code
1)
package com.kalyan.concurrency;
public class ThreadConfig {
public static final int size = 5;
}
2) package com.kalyan.concurrency;
public class State {
private volatile int state ;
public State() {
this.state =3;
}
public State(int state) {
this.state = state;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
}
3) package com.kalyan.concurrency;
public class Thrd implements Runnable {
int i ;
int name;
int prevThread;
State s;
public Thrd(int i,State s) {
this.i=i;
this.name=i;
this.prevThread=i-1;
if(prevThread == 0) prevThread=ThreadConfig.size;
this.s=s;
}
#Override
public void run() {
while(i<50)
{
synchronized(s)
{
while(s.getState() != prevThread)
{
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
synchronized(s)
{
//if(s.getState() ==3)
if(s.getState()==prevThread)
System.out.println("t"+ name+ i);
s.setState(name);
i = i +ThreadConfig.size ;
s.notifyAll();
}
}
}
}
4)
package com.kalyan.concurrency;
public class T1t2t3 {
public static void main(String[] args) {
State s = new State(ThreadConfig.size);
for(int i=1;i<=ThreadConfig.size;i++)
{
Thread T = new Thread(new Thrd(i,s));
T.start();
}
}
}
OUTPUT:
t11
t22
t33
t44
t55
t16
t27
t38
t49
t510
t111
t212
t313
t414
t515
t116..............
I hope I understood you right, but there are to main "features" in java to make a variable being shared between threads:
the volatile keyword
volatile int number = 1;
AtomicInteger (a standard java class -> no library)
AtomicInteger number = new AtomicInteger(1);
These two techniques should both do what you want, however I have no experience using it, I just came upon this word, didn't know what it means and did some digging.
Some stuff to read: ;)
volatile for java explained --> http://java.dzone.com/articles/java-volatile-keyword-0
a better explanation (with IMAGES!!) but for c# (which is still the same usage) --> http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/
And a link to some usages of AtomicInteger --> https://stackoverflow.com/a/4818753/4986655
I hope I could help you or at least send you in the right direction :)
- superfuzzy
I have two threads. One is a producer (class Deliver), second is consumer (class Produce). I want to simulate door producer. So producer deliver wood that consumer can produce a door. But i do not real get how to communicate between those two threads. Now when i run my program only wood is delivered but doors are not produced. I do not get why.
public class Deliver implements Runnable {
private static int MAX_STOCKPILE = 15;
private Integer wood;
public Deliver(Integer wood) {
this.wood = wood;
new Thread(this, "Deliver").start();
}
public synchronized void deliver() throws InterruptedException{
Thread.sleep(500);
if (wood < MAX_STOCKPILE) {
wood++;
System.out.println("Wood delivered" + " | Wood stockpile: " + wood);
notify();
}
else {
wait();
}
}
#Override
public void run() {
while (true) {
try {
deliver();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Produce implements Runnable{
private Integer wood;
public Produce(Integer wood) {
this.wood = wood;
new Thread(this, "Produce").start();
}
public synchronized void produce() throws InterruptedException{
Thread.sleep(1000);
if (wood == 10) {
wood -= 10; //produce
System.out.println("Doors produced");
notify();
}
else {
wait();
}
}
#Override
public void run() {
while (true) {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
Integer wood = 0;
new Deliver(wood);
new Produce(wood);
}
}
Now when i run my program only wood is delivered but doors are not produced. I do not get why
There are multiple issues with your code :
When you mark an instance method as synchronized, any thread entering that method will obtain a lock on this (i.e the instance on which the method was called). Since this in Deliver refers to a Deliver instance and this in Produce refers to a Produce instance, the wait and notify calls are practically useless in this case as they are not interested in the same objects.
The golden rule to remember in Java is that it uses pass-by-value semantics. Primitives and references are therefore always passed by value. While you may assume that both Deliver and Produce will be modifying the same Integer passed to them from main, that is not the case.
That said, I would highly recommend that you consider using something like an ArrayBlockingQueue for solving this instead of reinventing the wheel with wait and notify.
Change
if (wood == 10) {
to
if (wood >= 10) {
in case the thread doesn't catch it when it == 10
Something to note is that Integer is immutable.
When you change the reference to the Integer you are creating a new object which has no relationship to the previous object.
What you want this an object which is shared between the two threads so when you change the value (but not the reference) they are looking at the same value.
e.g.
wood -= 10;
is the same as
wood = Integer.valueOf(wood.intValue() - 10);
I suggest using AtomicInteger and making the reference to it final to ensure you don't accidentally try to change the reference.
As Andrew Jenkins suggests; if you lock, notify/wait on unrelated objects, you don't have any thread safety. Once you have a shared object, you have to lock, notify/wait on that shared object.
I'll throw my solution into the mix, taking into account Peter Lawrey's advice about using AtomicInteger.
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String[] args) {
AtomicInteger wood = new AtomicInteger(0);
new Deliver(wood);
new Produce(wood);
}
}
public class Deliver implements Runnable {
private static int MAX_STOCKPILE = 15;
private final AtomicInteger wood;
public Deliver(AtomicInteger wood) {
this.wood = wood;
new Thread(this, "Deliver").start();
}
public void deliver() throws InterruptedException{
Thread.sleep(500);
synchronized(wood) {
if (wood.intValue() < MAX_STOCKPILE) {
wood.addAndGet(1);
System.out.println("Wood delivered" + " | Wood stockpile: " + wood);
wood.notify();
} else {
wood.wait();
}
}
}
#Override
public void run() {
while (true) {
try {
deliver();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Produce implements Runnable{
private final AtomicInteger wood;
public Produce(AtomicInteger wood) {
this.wood = wood;
new Thread(this, "Produce").start();
}
public void produce() throws InterruptedException{
synchronized(wood) {
if (wood.intValue() >= 10) {
wood.addAndGet(-10); //produce
System.out.println("Doors produced");
wood.notify();
}
else {
wood.wait();
}
}
}
#Override
public void run() {
while (true) {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Key changes:
We use a mutable object to communicate between threads (AtomicInteger).
We synchronize on the mutable object, not the thread being run.
This question already has answers here:
Should you synchronize the run method? Why or why not?
(6 answers)
Closed 7 years ago.
I need to create 2 classes, Class Player and Class Referee which implement Runnable interface(Basically, create threads).
The order in which the threads have to be executed are
Referee
Player 1 or 2
Referee
Player 1 or 2
and so on..
Here, is the solution that I came up with, but, the order doesn't seem to happen. Players keep playing even before referee completes checking.
``
public class a {
public static synchronized void main(String[] args) throws InterruptedException {
ready = false;
finish = false;
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Referee());
executorService.execute(new Player(1));
executorService.execute(new Player(2));
Thread.sleep(1000);
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.MINUTES);
}
/*....FOLLOWED BY GETTER AND SETTER METHODS
*
*
*/
}
class Player implements Runnable{
public synchronized void play() throws InterruptedException{
//continue playing unless game is over
while(true)
{
while( (a.getReady()) != true){
wait();
}
/***
*
*
*
execute some code to play
**/
//Change the value of the condition variable for the referee to start executing
a.putReady(false);
}
}
#Override
public void run() {
try {
play();
} catch (InterruptedException ex) {
Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
class Referee implements Runnable{
public synchronized void check() throws InterruptedException {
while(true)
{
/****INITIALIZING THE GAME***/
while(a.getReady())
wait();
//If some player has won, releasing locks and exiting the threads
if(winner != 0)
{
a.putReady(true);
a.putFinish(true);
return;
}
//If the boards are full and ends in a draw
else if(count_plays >= 42)
{
System.out.print("\n Board is full. Its a draw!!\n");
a.putReady(true);
a.putFinish(true);
return;
}
//If there is more space on the board to play
else
{
System.out.print("\nNo player has won, let the play resume!!\n");
//Thread.sleep((long)100);
}
/* Code for checking if there has been a winner
*
*
*/
a.putReady(true);
notify();
}
}
#Override
public void run(){
try {
check();
}
catch (InterruptedException ex) {
Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
`
I understand that threads of different objects cannot be synchronized and there is no point in serializing the code that is under synchronization. This is a task that I have been assigned. In the above code, Players play simultaneously even after providing a set of condition variables and do not allow thread of the referee to check for the winner each time they play.
Please, give me an outline of the code to provide such an output using synchronized method, notify() and wait().
It is allowed but rarely makes sense and would not make sense in your case. The two threads would be synchronizing on different objects which would have no effect. The point of the synchronized method is to prevent two threads from simultaneously accessing the same object. If the two players need to access some common object but you don't want the accesses to overlap you should synchronize on that object or synchronize one of the methods of that object. You should only be within a synchronized block or method for as little time as possible. synchronizing unnecessarily can lead to poor performance or deadlock.
The closest that made any sense to me was this:
a
public static class a {
static boolean finish = false;
public static void main(String[] args) throws InterruptedException {
finish = false;
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Referee());
executorService.execute(new Player(1));
executorService.execute(new Player(2));
// wait for user to press enter, just for testing
new Scanner(System.in).nextLine();
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.MINUTES);
}
}
Player
public class Player implements Runnable {
final int playernum;
public Player(int playernum) {
this.playernum = playernum;
}
#Override
public void run() {
try {
while (!a.finish) {
synchronized (a.class) {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("player " + playernum + " does step " + i);
}
}
Thread.sleep(1000);
}
} catch (InterruptedException interruptedException) {
}
}
}
Referee
public class Referee implements Runnable {
#Override
public void run() {
try {
while (!a.finish) {
synchronized (a.class) {
System.out.println("Check for winner.");
}
Thread.sleep(1000);
}
} catch (InterruptedException interruptedException) {
}
}
}
Notice that it is not synchronized during the entire run only during an internal block inside.
It should produce something like this:
Check for winner.
player 1 does step 0
player 1 does step 1
player 1 does step 2
player 1 does step 3
player 1 does step 4
Check for winner.
player 2 does step 0
player 2 does step 1
player 2 does step 2
player 2 does step 3
player 2 does step 4
Without synchronization you would not see all 5 steps from each player with no intervening checks or steps from the other player.
This is a part of my program. I am convinced that this class is where my code is getting hung up. I am using deadlock thread in java and I have difficulties.
So I did not want to display my entire code but this is a sample. Can someone tell me why it is hanging? this deadlock situation is confusing me.
public class gameEnemyRelease {
private static Object enemy1 = new Object();
public static Object enemy2= new Object();
public static void main(String args[]) {
player1 p1 = new player1();
player2 p2 = new player2();
p1.start();
p2.start();
}
private static class player1 extends Thread {
public void run() {
synchronized (enemy1) {
System.out.println("Start Launch");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Waiting for enemy 2 to launch...");
synchronized (enemy2) {
System.out.println("Shot");
}
}
}
}
private static class player2 extends Thread {
public void run() {
synchronized (enemy2) {
System.out.println("...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("");
synchronized (enemy1) {
System.out.println("");
}
}
}
}
}
Your program is hanging probably because neither of the threads in position to proceed and waiting for each other to release the lock. So you can try changing this method; Try the below code:
private static class player2 extends Thread {
public void run() {
synchronized (enemy1) {
System.out.println("...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("");
synchronized (enemy2) {
System.out.println("");
}
}
Think about this code path:
Thread 1 locks Enemy 1
Thread 2 locks Enemy 2
Threads 1 try to lock Enemy 2 but is locked by thread 2, so it waits
Thred 2 try to lock Enemy 1 but is locked by thread 1, so it waits
You need to address and probably lock both enemies from start.
I have to create two Threads which have to poll and object from a queue in 2 seconds intervals.
The first Thread poll and object then wait and notify the second one to poll the object from it's queue.
I read all about wait and notify but nothing works with me.
Any sugestions?
First thread:
public class SouthThread extends Thread {
private Queue<Car> q = new LinkedList<Car>();
public void CreateQueue() {
Scanner input = new Scanner(System.in);
for (int i = 0; i < 2; i++) {
Car c = new Car();
System.out.println("Enter registration number: ");
String regNum = input.nextLine();
c.setRegNum(regNum);
q.offer(c);
}
}
public int getQueueSize() {
return q.size();
}
#Override
public void run() {
while (q.size() != 0)
try {
while (q.size() != 0) {
synchronized (this) {
System.out.print("The car with registration number: ");
System.out.print(q.poll().getRegNum());
System.out
.println(" have passed the bridge from the south side.");
this.wait(2000);
notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Second thread:
public class NorthThread extends Thread {
private Queue<Car> q = new LinkedList<Car>();
public void CreateQueue() {
Scanner input = new Scanner(System.in);
for (int i = 0; i < 2; i++) {
Car c = new Car();
System.out.println("Enter registration number: ");
String regNum = input.nextLine();
c.setRegNum(regNum);
q.offer(c);
}
}
public int getQueueSize() {
return q.size();
}
#Override
public void run() {
try {
while (q.size() != 0) {
synchronized (this) {
System.out.print("The car with registration number: ");
System.out.print(q.poll().getRegNum());
System.out
.println(" have passed the bridge from the north side.");
this.wait(2000);
notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Main Thread:
public class Main {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
SouthThread tSouthThread = new SouthThread();
NorthThread tNorthThread = new NorthThread();
tSouthThread.CreateQueue();
tNorthThread.CreateQueue();
System.out.println(tSouthThread.getQueueSize());
tSouthThread.start();
tNorthThread.start();
}
}
It seems that what you basically want to achieve is a system that alternates control between two independent units so that each of the units gets some time to process followed by a two second waiting period (or vice versa).
There are two main ways you could achieve this:
Using a central control
With autonomous communicating agents
The first approach is a bit easier. Here, you have a central "master" component which takes care of coordinating who gets the processing time and also implements the wait times. For that approach, the two independent units do not even have to be Threads:
public class South {
private Queue<Car> q = new LinkedList<Car>();
public void CreateQueue() { ... }
public void poll() {
System.out.print("The car with registration number: ");
System.out.print(q.poll().getRegNum());
System.out.println(" have passed the bridge from the South side.");
}
}
public class North {
private Queue<Car> q = new LinkedList<Car>();
public void CreateQueue() { ... }
public void poll() {
System.out.print("The car with registration number: ");
System.out.print(q.poll().getRegNum());
System.out.println(" have passed the bridge from the North side.");
}
}
// This is the "master" class
public class Main {
public static void main(String[] args) {
South south = new South();
North north = new North();
south.CreateQueue();
north.CreateQueue();
boolean done = false;
while (!done) {
try {
Thread.sleep(2000);
} (catch InterruptedException) { /* TODO */ }
north.poll();
try {
Thread.sleep(2000);
} (catch InterruptedException) { /* TODO */ }
south.poll();
}
}
}
Note that North and South do not inherit from Thread here, i.e., they are just plain old objects.
(However, if your program is more complex and North/South are only one part of it, you might want to make Main(!) a separate thread and put the above while-loop inside the thread's run method, so that the rest of the program can run concurrently.)
In the second approach, you don't have such a central control component, but the both North and South run in their own separate threads. This then requires that they coordinate who's allowed to process by communicating with each other.
public class SouthThread extends Thread {
protected Queue<Car> q = new LinkedList<Car>();
protected North north;
public void CreateQueue() { ... }
public void poll() { ... }
public void run() {
boolean done = false;
while (!done) {
// wait two seconds
try {
Thread.sleep(2000);
} (catch InterruptedException) { /* TODO */ }
// process one element from the queue
poll();
// notify the other thread
synchronized (north) {
north.notifyAll();
}
// wait until the other thread notifies this one
try {
synchronized (this) {
wait();
}
} (catch InterruptedException) { /* TODO */ }
}
}
}
public class NorthThread extends Thread {
protected Queue<Car> q = new LinkedList<Car>();
protected South south;
public void CreateQueue() { ... }
public void poll() { ... }
public void run() {
boolean done = false;
while (!done) {
// wait two seconds
try {
Thread.sleep(2000);
} (catch InterruptedException) { /* TODO */ }
// process one element from the queue
poll();
// notify the other thread
synchronized (south) {
south.notifyAll();
}
// wait until the other thread notifies this one
try {
synchronized (this) {
wait();
}
} (catch InterruptedException) { /* TODO */ }
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
SouthThread tSouthThread = new SouthThread();
NorthThread tNorthThread = new NorthThread();
tSouthThread.north = tNorthThread;
tNorthThread.south = tSouthThread;
tSouthThread.CreateQueue();
tNorthThread.CreateQueue();
tSouthThread.start();
tNorthThread.start();
}
}
A more general remark: since both North and South seem to be doing basically the same, there's probably no need to implement them in two separate classes. Instead, it should be sufficient to have only one class that implements the desired functionality and instantiate it twice:
// We can combine the functionality of North and South
// in a single class
public class NorthSouth {
public void CreateQueue() { ... }
public void poll() { ... }
// etc.
}
public class Main {
public static void main(String[] args) {
NorthSouth north = new NorthSouth();
NorthSouth south = new NorthSouth();
north.CreateQueue();
south.CreateQueue();
// etc.
}
}
wait and notify must refer to the same lock: When you call object.wait(2000) what you're saying is "I'm going to wait here for 2000 millis, or until someone else calls object.notify() where object refers to me"
I still don't completely understand what you want to achieve, but if you simply want two threads that concurrently do:
Do something
Wait 2 seconds
GOTO 1
then you don't need wait/notify at all, you could get around using Thread.sleep() or potentially two instances of java.util.Timer.
But again, I'm not sure I understand correctly. :-(