I am writing a barbershop program using threads. Currently I have one barber and multiple customers coming in at the same time. However, after the first run through the program, the rest of the customers get all messed up. They all sit down at the same time. Is there something that I missed? My code is:
public synchronized void enter(Customer cust) {
custList.add(cust);
getCut(cust);
}
public synchronized void getCut(Customer cust) {
try {
notify();
wait();
System.out.println("sit down");
notify();
if (cashier==0) {
cashier++;
wait();
System.out.println("waiting to pay");
notify();
wait();
System.out.println("left the room");
chairs++;
cust.terminate();
}
} catch (InterruptedException ie) {}
}
This is my barber part of it:
public synchronized void cut(Barber barb) {
cashier=0;
try {
if(temp){
System.out.println(temp);
temp = false;
notify();
wait(); //wait for the customer to be settled in
System.out.println("go to cus");
notify();
wait();
System.out.println("cut cus hair");
notify();
wait();
if (cashier==1) {
System.out.println("got money");
notify();
cashier--;
barbers++;
}
}
} catch (InterruptedException ie) {}
}
}
public synchronized void goCut(Barber barb) {
cashier=0;
try {
if(temp){
System.out.println(temp);
temp = false;
notify();
wait();
System.out.println("walks to cus");
notify();
wait();
System.out.println("cut hair");
notify()
wait();
if (cashier==1) {
System.out.println("got the money");
notify();
cashier--;
barbers++;
}
}
From the oracle site
Note: Always invoke wait inside a loop that tests for the condition being waited for. Don't assume that the interrupt was for the particular condition you were waiting for, or that the condition is still true.
Please refer to Guarded blocks multithreading
It looks like you are using notify and wait randomly.
You have
notify();
wait();
at the beginning of the getCut method, what it does is:
the first client comes in, it calls notify, and then waits
the second client comes in, it calls notify - and thus it wakes the first client, and then it waits
the third client comes in, it calls notify - in result the second client wakes up and so on
Instead you should thing of using notify and wake to block a particular resource (chair).
private final Object pChairLock = new Object();
private int pAvaliableChairs = 3;
...
// take the resource
synchronized(pChairLock)
{
// wait until a chair is avaliable
while(pAvaliableChairs == 0)
{
pChairLock.wait();
}
// take sit
pAvaliableChairs--;
}
// now the current thread 'is sitting'
// - it can do some work using the resource
// after finishing, release the resource
synchronized(pChairLock)
{
pAvaliableChairs--;
// notify all waiting thread that resource is available
pChairLock.notifyAll();
}
In this case you could just use notify(), but if different threads are waiting to release resource and to take it, then calling notify could wake a wrong thread.
Don't worry about waking too much thread at the same time, as each thread will check if the resource is available and only the first one will be able to take it - the rest will resume waiting.
This example uses three chairs, but you can use just one (boolean) or any other number.
You can do the same with cashiers.
Use the code below as a template (from Magee & Kramer's textbook)...
ProducerConsumer = BarberShop
create BarberShop with size of 1
get = giveCut (barber "gets" a customer and gives customer a haircut)
put = getCut (customer requests a haircut - i.e. "puts" a customer request for a haircut)
code:
public class ProducerConsumer {
protected Object[] buf;
protected int count = 0;
protected int size;
public ProducerConsumer(int size) {
this.size = size;
buf = new Object[size];
}
public synchronized void put(Object o) throws InterruptedException {
while (count == size) wait();
buf[count] = o;
++count;
notifyAll();
}
public synchronized Object get() throws InterruptedException {
while (count == 0) wait();
--count;
Object o = buf[count];
buf[count] = null;
notifyAll();
return (o);
}
}
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.
I was trying to implement a reader-writer using notify and wait. But i think I'm stuck.
My sequence goes like this.
RRRRRRRRRRWWWWWWWWW This happens if the main start with reader invoked first.
Or
WWWWWWWRRRRRRRRRRR. This happens if the main start with the writer invoked first.
Looks like reads notify isn't working at all. Writer thread never goes into execution.
If i make while loop in run method to run infinite then it's just
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR......... No chance for the writer to write.
Can you have a look at this?
DATA CLASS
public class Data {
private int q ;
private boolean isAnyOneReading;
public Data() {
}
public void readQ() {
synchronized (this){
isAnyOneReading = true;
System.out.println("Read start "+q);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this){
isAnyOneReading = false;
System.out.println("Read end "+q);
notifyAll();
}
}
public synchronized void writeQ(int q) {
System.out.println(isAnyOneReading);
while (isAnyOneReading){
try{
wait();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("Done");
Thread.currentThread().interrupt();
}
}
System.out.println("Write start "+q);
this.q = q;
try{
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
System.out.println("Write end "+q);
notifyAll();
}
}
READER CLASS
public class Reader implements Runnable {
private Data data;
private Thread readerThread;
public Reader(Data data) {
this.data = data;
readerThread = new Thread(this, "ReaderThread");
}
void startThread(){
readerThread.start();
}
#Override
public void run() {
int i = 0 ;
while (i != 5){
data.readQ();
i++;
}
}
}
WRITER CLASS
public class Writer implements Runnable{
private Data data;
private Thread writerThread;
public Writer(Data data) {
this.data = data;
writerThread = new Thread(this,"WriterThread," );
}
void startThread(){
writerThread.start();
}
#Override
public void run() {
int i = 0 ;
int j = 0 ;
while (j != 5){
data.writeQ(i++);
// i++;
j++;
}
}
}
MAIN CLASS
public class ReaderWriterDemo {
public static void main(String[] args) {
Data data = new Data();
Reader reader = new Reader(data);
Writer writer = new Writer(data);
reader.startThread();
writer.startThread();
}
}
Try removing the Thread.sleep from Data class.
And add Thread.sleep in run methods like so. (pasting one example):
#Override
public void run() {
int i = 0;
while (i != 5) {
data.readQ();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
i++;
}
}
}
Read's notifyAll() works, but it seems that read() re-called again and changes isAnyOneReading's value prior to any other action in write(). That's why check fails and write() starts waiting again. As Danny Fried suggested moving Thread.sleep() to the run methods will help.
Looks like a simple case of starvation. Consider your writer's main loop:
while (j != 5){
data.writeQ(i++);
// i++;
j++;
}
data.writeQ() is a synchronized method: The very last thing it does before it returns is to unlock the lock. The very first thing it does on the next call is to re-lock the lock. Not much happens in-between--increment and test a local variable is all.
Java synchronized locks are not fair. (i.e., when a lock becomes available, the system does not guarantee that the winner will be the thread that's been waiting the longest.) In fact, it may be be the opposite of fair: The OS may try to maximize efficient use of the CPU(s) by always choosing the thread that's easiest to wake up.
When the writer comes back to call data.writeQ() on each subsequent iteration, it may be that the OS has not even have started to wake up the reader, and it simply lets the writer enter the synchronized block again.
Same thing happens with your reader. The code is a bit more complicated, but just like in the writer, the very last thing that data.readQ() does before returning is to unlock the lock, and the very first thing that it does on the next call is to lock it again.
Brute force solution: replace the synchronized blocks with a fair ReentrantLock object.
Alternate solution, which is more typical of how many programs actually work: Have the threads do something else (e.g., have them do some I/O) in between calls to the locked function, thereby giving the other threads a chance to get in and use the locked resource.
I've got a test on java thread coding but i have some basic problem.. after hours of trying and searching I decided to try there!
I can't understand why my wait is still locked even after my notify :
Here you can find my code:
public class Mymain {
public static void main(String[] args) {
for( int i=0;i<100;i++){
new ThreadClass(i).start();
}
}
}
public class ThreadClass extends Thread {
static boolean ok = false;
int id;
public ThreadClass(int i) {
id = i;
}
public void run() {
System.out.println("Thread start " + id);
Last.toDo(id);
if (id == 5)
try {
waiting();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (id != 5)
awaking();
System.out.println("thread end " + id);
}
private synchronized void awaking() {
// TODO Auto-generated method stub
if (ok) {
System.out.println("i'm " + id + " and i'm Awaking 5");
ok = false;
notify();
System.out.println("I did the notify and i'm " + id);
}
}
private synchronized void waiting() throws InterruptedException {
System.out.println("Sleeping");
ok = true;
wait();
System.out.println("Awake 5");
}
}
Result
Then it starts looping or it goes in dead lock not sure.. it should just stop the thread with id=5 and then the next thread should re-start the id = 5.. but thread 5 never wake up after the notify...
In the result as you can see I got 2 threads trying to wake up the thread 5 and thread 5 is always waiting since the start^^
The issue is that you are not calling notify() on the same object that you called wait() on. In particular, thread 5 is calling wait() on itself, but thread 8, for example, is calling notify() on itself, not on thread 5. As a result, thread 5 is never getting notified.
Also, you need to make the ok variable volatile to ensure that when one thread sets it, the other threads can see the change. This isn't causing you a problem in this particular case, but it could cause a problem in other cases.
Why you don't use notifyAll() method? When you invoke notify(), it means that only one thread will change a status from waiting to runnable, but there can be the situations when you have more than one thread and other threads which are waiting in the line as well, they will not receive this notification. In my opinion it is preferable to use notifyAll.
i can't understand why my wait is still locked even after my notify :
Wait and notify work when the same object instance is used. If you for example have:
String x1 = "...";
String x2 = "...";
and thread #1 does:
synchronized (x1) { x1.wait(); }
and thread #2 then does:
synchronized (x2) { x2.wait(); }
Then thread #1 will still be waiting because the notify was only for x2. In your example, the thread with id 5 is waiting on its own instance of ThreadClass since you are using method synchronization. Then when other threads call awaking() they too are calling notify on their instances of ThreadClass. If you want thread #5 to see the other thread's notify then they should share a lock object.
Maybe something like:
final Object lock = new Object();
for (int id = 0; id < 100; id++){
new ThreadClass(id, lock).start();
}
...
public class ThreadClass extends Thread {
private final Object lock;
...
public ThreadClass(int id, Object lock) {
this.id = id;
this.lock = lock;
}
...
private void awaking() {
...
synchronized (lock) {
lock.notify();
}
...
}
private void waiting() throws InterruptedException {
...
synchronized (lock) {
lock.wait();
}
...
}
}
Look I did a few changes to your code:
You can't just notify() , you'll notify to this. And you can't just wait() , you'll wait forever. You have to use these function over an Object, so i added an Integer object (just to show you - you'll have to choose the right object).
You have yo understand between synchronized and static synchronized. A quick search would lead you to a perfect answer.
Why function waiting() is synchronized? only thread number 5 calls it.
When calling to an Object.notify() / Object.wait(), you have to declare a synchronized block over the object.
Here's some code:
public class Threads {
public static void main(String[] args) {
Integer intObject = new Integer(0);
for( int i=0;i<100;i++){
new ThreadClass(i, intObject).start();
}
}
}
class ThreadClass extends Thread {
static boolean ok = false;
int id;
Integer intObject;
public ThreadClass(int i, Integer intObject) {
id = i;
this.intObject = intObject;
}
public void run() {
System.out.println("Thread start " + id);
//Last.toDo(id);
if (id == 5)
waiting();
else
awaking(this);
System.out.println("thread end " + id);
}
private static synchronized void awaking(ThreadClass t) {
if(ok) {
System.out.println("i'm " + t.id + " and i'm Awaking 5");
ok = false;
synchronized (t.intObject) {
t.intObject.notify();
}
System.out.println("I did the notify and i'm " + t.id);
}
}
private void waiting(){
System.out.println("Sleeping");
ok = true;
synchronized (intObject) {
try {
intObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Awake 5");
}
}
I am having troubles with stopping a thread which is started from outside the class using a actionPerformed on a JButton. Code of the thread class below.
public synchronized void run ()
{
try
{
do
{
int minuta = vrijeme / 60;
int sekundi = vrijeme % 60;
System.out.println(minuta+" "+sekundi);
vrijeme = vrijeme - 1;
delay = delay - 1000;
if (minuta == stani && sekundi == 0)
{
}
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
while (delay != 0);
{
//
}
}
catch (Exception e)
{
System.out.println("Stao" + e);
}
}
void pokreniThread()
{
(new Thread(new OdredenoVrijeme())).start();
}
synchronized public void zaustaviThread()
{
try
{
(new Thread(new OdredenoVrijeme())).wait();
}
catch (Exception e)
{
System.out.println("stao" +e);
}
}
}
Every time i call .sleep() .wait() or anything similar i get the following catch message:
java.lang.IllegalMonitorStateException
Under Java, you cannot have a sleep in the main process. Create a sub-thread, which will do the sleep, then post a message to a handler in the main-thread, to do something after the timeout.
If you want to stop a thread itself, set a variable inside the thread like is_stopping=true, then inside the thread you could set a variable is_running=false after the thread stops itself.
is_running=true;
while (is_running & !is_stopping)
{
do_something();
sleep();
}
is_stopping=false;
is_running=false;
In java the main thread is playing a scheduler part in the program. So in a multithreading situation you have these parts:
scheduler/controller
provider
customer
The main thread should always play the scheduler/controller part of the program. BTW you are not using multithreading in a good way. use synchronized when its absolutely necessary.
look at the following code. you should use synchronization like this:
public class BlockingQueue<T> {
private Queue<T> queue = new LinkedList<T>();
private int capacity;
public BlockingQueue(int capacity) {
this.capacity = capacity;
}
public synchronized void put(T element) throws InterruptedException {
while(queue.size() == capacity) {
wait();
}
queue.add(element);
notify(); // notifyAll() for multiple producer/consumer threads
}
public synchronized T take() throws InterruptedException {
while(queue.isEmpty()) {
wait();
}
T item = queue.remove();
notify(); // notifyAll() for multiple producer/consumer threads
return item;
}
You cannot stop a thread from an external context. The thread should stop itself when some condition changes.
You have to hold a flag in your thread that you want to stop, and the thread to check the flag in a loop. If the flag is changed, then the thread itself should do nothing and it will exit by itself
As I Know only one thread can execute on a synchronize method on same block but in below producer consumer problem I am able to run both the methods.
Sample Code
import java.util.concurrent.CountDownLatch;
public class VIV {
public static void main(String[] args) throws Exception {
Number no = new Number();
//Same Object is passed
Even ev = new Even(no, 10);
Odd od = new Odd(no, 10);
Thread oddThraed = new Thread(od,"ODD");
oddThraed.start();
Thread evenThraed = new Thread(ev,"Even");
evenThraed.start();
}
}
class Number {
int no;
boolean flag=false;
public synchronized int getEvenNo() {
System.out.println("In Even Method");
// wait block so no other thread can enter on same object synchronized method
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
if(!flag) {
try {
Thread.sleep(1000);
}catch (Exception e) {
// TODO: handle exception
}
}
no=no+1;
System.out.println(Thread.currentThread().getName()+":"+no);
flag=false;
notify();
return no;
}
public synchronized int getOddNo() {
System.out.println("In ODD Method");
// wait block so no other thread can enter on same object synchronized method
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
if(flag) {
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
}
no = no+1;
System.out.println(Thread.currentThread().getName()+":"+no);
flag=true;
notify();
return no;
}
}
class Even implements Runnable {
Number num;
int noOfTime;
Even(Number no, int noOfTime) {
this.num=no;
this.noOfTime=noOfTime;
}
public void run() {
for(int i=0;i<noOfTime;i++) {
num.getEvenNo();
}
}
}
class Odd implements Runnable {
Number num;
int noOfTime;
Odd(Number no, int noOfTime) {
this.num=no;
this.noOfTime=noOfTime;
}
public void run() {
for(int i=0;i<noOfTime;i++) {
num.getOddNo();
}
}
}
OutPut :
In ODD Method
In Even Method
As Only one Number object is created and passed to other classes which are invoking on its two different synchronized methods. Both methods are printing the message after that waiting .
The reason that both methods get executed at the same time is that the wait() method releases the lock. Once your synchronized method calls wait(), the lock is given back, and another thread can invoke another synchronized method on the same object. Don't call wait() inside a synchronized method in this way!
The wait() calls are also the reason that you're getting deadlock. This is what is happening:
The odd method acquires the lock and starts executing.
The odd method prints its first message.
The odd method invokes wait(), which releases the lock and waits to be notified.
The even method can now acquire the lock that's been released.
The even method prints its first message.
The even method invokes wait(), which releases the lock and waits to be notified.
By this point, you're in the middle of both synchronized methods (because wait() releases the lock), and you're deadlocked (because both methods are waiting).
Don't call wait() unless you're quite sure that's what you need. If your wait() is there just to keep it waiting to see if the synchronization can be broken, you might try Thread.sleep() instead, which will pause without releasing any locks. Usually it's enough to declare the relevant methods or blocks as synchronized without needing any wait / notify.
(By the way, it's not a good idea to have a class called Number, because this is a standard JDK class. It's the superclass of Double, Integer, and so on.)
I don't know whether you are trying to achieve this kind of thing, if you are trying to call EVEN & ODD alternatively, then I have modified your code for the same. Have a look at below code :-
public class VIV {
public static void main(String[] args) throws Exception {
TestNumber no = new TestNumber();
// Same Object is passed
Even ev = new Even(no, 10);
Odd od = new Odd(no, 10);
Thread oddThraed = new Thread(od, "ODD");
oddThraed.start();
Thread evenThraed = new Thread(ev, "Even");
evenThraed.start();
}
}
class TestNumber {
int no;
boolean flag = false;
public synchronized int getEvenNo() {
System.out.println("In Even Method");
// wait block so no other thread can enter on same object synchronized
// method
no = no + 1;
System.out.println(Thread.currentThread().getName() + ":" + no);
flag = false;
notify();
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
if (!flag) {
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
}
return no;
}
public synchronized int getOddNo() {
System.out.println("In ODD Method");
no = no + 1;
System.out.println(Thread.currentThread().getName() + ":" + no);
flag = true;
notify();
// wait block so no other thread can enter on same object synchronized
// method
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
if (flag) {
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
}
return no;
}
}
class Even implements Runnable {
TestNumber num;
int noOfTime;
Even(TestNumber no, int noOfTime) {
this.num = no;
this.noOfTime = noOfTime;
}
public void run() {
for (int i = 0; i < noOfTime; i++) {
num.getEvenNo();
}
}
}
class Odd implements Runnable {
TestNumber num;
int noOfTime;
Odd(TestNumber no, int noOfTime) {
this.num = no;
this.noOfTime = noOfTime;
}
public void run() {
for (int i = 0; i < noOfTime; i++) {
num.getOddNo();
}
}
}
Note : As suggested by #chiastic-security Number is already defined in JDK, I have renamed it to TestNumber in this code.
Output :
In ODD Method
ODD:1
In Even Method
Even:2
In ODD Method
ODD:3
In Even Method
Even:4
In ODD Method
ODD:5
In Even Method
Even:6
In ODD Method
ODD:7
In Even Method
Even:8
In ODD Method
ODD:9
In Even Method
Even:10
In ODD Method
ODD:11
In Even Method
Even:12
In ODD Method
ODD:13
In Even Method
Even:14
In ODD Method
ODD:15
In Even Method
Even:16
In ODD Method
ODD:17
In Even Method
Even:18
In ODD Method
ODD:19
In Even Method
Even:20