I am trying to do a little exercise on threads and I just started learning thread and other stuff.
import java.util.logging.Level;
import java.util.logging.Logger;
public class ThreadDemo extends Thread {
#Override
public void run() {
int count = 0;
for (int i = 0; i <= 5; i++) {
count++;
System.out.println("counting" + count);
}
if (count == 3) {
try {
Thread t = new Thread();
t.wait(5000);
System.out.println("thread waiting");
} catch (InterruptedException ex) {
Logger.getLogger(ThreadDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public static void main(String[] args) {
ThreadDemo obj = new ThreadDemo();
obj.start();
}
}
Output of the given
counting1
counting2
counting3
counting4
counting5
counting6
When the test if (count == 3) is done the value of count is 6.
And your code test it only once.
You need to move the code that is out of the for loop inside it.
You need also to hold a lock on t before call wait. This is done with a synchronized block.
#Override
public void run() {
int count = 0;
for (int i = 0; i <= 5; i++) {
count++;
System.out.println("counting" + count);
// Moved block
if (count == 3) {
try {
Thread t = new Thread();
synchronized (t) {
t.wait(5000);
}
System.out.println("thread waiting");
} catch (InterruptedException ex) {
Logger.getLogger(ThreadDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
// End of moved block
}
}
The output will be
counting1
counting2
counting3
thread waiting // Note: this will be printed after 5 seconds
counting4
counting5
counting6
A similar result, but not identical can be obtained using Thread.sleep, replacing this code
Thread t = new Thread();
synchronized (t) {
t.wait(5000);
}
With the following:
Thread.sleep(5000);
A difference between Thread.sleep and Object.wait is that is possible to awake a thread waiting acquiring his lock and calling notify (or notifyAll).
Instead is not possible to awake a thread sleeping with Thread.sleep.
Related
Hi I have been trying to solve the producer consumer problem in java without semaphores. When I use single producer and single consumer then my code is working fine. But when I add more than one consumer then it is completely messing up, all the consumer threads are going into the synchronized block. I'm not sure why this is happening. Here is my code :
Producer class:
public class Producer implements Runnable {
Object SharedObject = null;
String producerName= null;
Random rn = new Random();
public Producer(Main m, String s) {
this.SharedObject = m;
this.producerName=s;
}
public Producer(Main m) {
this.SharedObject = m;
}
public void run() {
while (true) {
synchronized (SharedObject) {
if (Main.itemCount == Main.bufferSize) {
try {
System.out.println("Producer is sleeping and waiting for notification form Consumer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount++;
System.out.println(this.producerName+" Produced the item and the item count is : " + Main.itemCount);
if (Main.itemCount == 1) {
SharedObject.notify();
System.out.println("Producer Notified the cosumer to wake up");
}
}
try {
int i = rn.nextInt(100);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Consumer Class:
public class Consumer implements Runnable {
Object SharedObject = null;
String consumerName= null;
Random rn = new Random();
public Consumer(Main m, String s) {
SharedObject = m;
this.consumerName=s;
}
Consumer c= new Consumer((Main) SharedObject,consumerName);
synchronized void consume(){
synchronized (SharedObject) {
if (Main.itemCount == 0) {
try {
System.out.println(this.consumerName+" is sleeping and waiting for notify from Producer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount--;
System.out.println(this.consumerName+" consumed 1 item and the item Count is " + Main.itemCount);
if (Main.itemCount == 4) {
SharedObject.notifyAll();
System.out.println("Consumer notified the producer to wake up");
}
}
}
public void run() {
while (true) {
c.consume();
try {
int i = rn.nextInt(100);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Main Class:
public class Main {
static int itemCount = 0;
static int bufferSize = 5;
public static void main(String[] args) {
Main m = new Main();
Thread objP = new Thread(new Producer(m, "Producer1"));
Thread objC = new Thread(new Consumer(m, "Consumer1"));
Thread objC2 = new Thread(new Consumer(m, "Consumer2"));
Thread objC3 = new Thread(new Consumer(m, "Consumer3"));
objP.start();
objC.start();
objC2.start();
objC3.start();
}
}
You are using notifyAll in the producer, which wakes up all consumer threads waiting on the monitor. If you want only one consumer to wake up, you should use notify From the API documentation:
notify()
Wakes up a single thread that is waiting on this object's monitor.
notifyAll()
Wakes up all threads that are waiting on this object's monitor.
It would also be better for your consumers to actually check that they can consume a resource when they are woken up. If you want to continue to use notifyAll, a consumer should be able to be awoken, and if insufficient resource is available, go back to waiting.
I suggest printing the main.itemCount. This will make it more obvious what the problems you have are.
You have to pay attention to when you are calling notify.
Why does your producer only call notify when there is exactly one item available? Shouldn't the producer call notify whenever there is an item available?
The consumer only tells the producer to wake up when there are 4 items (isn't this full?).
Actually changing notifyAll() to notify() kindoff worked!!! thanks for ua suggestion guys. Here is my code:
Producer class:
package com.source;
import java.util.Random;
public class Producer implements Runnable {
Object SharedObject = null;
String producerName = null;
Random rn = new Random();
public Producer(Main m, String s) {
this.SharedObject = m;
this.producerName = s;
}
public Producer(Main m) {
this.SharedObject = m;
}
public void run() {
while (true) {
synchronized (SharedObject) {
if (Main.itemCount == Main.bufferSize) {
try {
System.out
.println(this.producerName + "is sleeping and waiting for notification form Consumer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount++;
System.out.println(this.producerName + " Produced the item and the item count is : " + Main.itemCount);
if (Main.itemCount == 1) {
SharedObject.notify();
System.out.println("Producer Notified the cosumer to wake up");
}
}
try {
int i = rn.nextInt(100);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Consumer Class:
package com.source;
import java.util.Random;
public class Consumer implements Runnable {
Object SharedObject = null;
String consumerName = null;
Random rn = new Random();
public Consumer(Main m, String s) {
SharedObject = m;
this.consumerName = s;
}
public void run() {
while (true) {
synchronized (SharedObject) {
if (Main.itemCount == 0) {
try {
System.out.println(this.consumerName + " is sleeping and waiting for notify from Producer");
SharedObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Main.itemCount--;
System.out.println(this.consumerName + " consumed 1 item and the item Count is " + Main.itemCount);
if (Main.itemCount == 4) {
SharedObject.notify();
System.out.println("Consumer notified the producer to wake up");
}
}
try {
int i = rn.nextInt(1000);
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Main Class:
package com.source;
public class Main {
static int itemCount = 0;
static int bufferSize = 5;
public static void main(String[] args) {
Main m = new Main();
Thread objP = new Thread(new Producer(m, "Producer1"));
Thread objC = new Thread(new Consumer(m, "Consumer1"));
Thread objC2 = new Thread(new Consumer(m, "Consumer2"));
Thread objC3 = new Thread(new Consumer(m, "Consumer3"));
Thread objP2 = new Thread(new Producer(m, "Producer2"));
Thread objP3 = new Thread(new Producer(m, "Producer3"));
objP.start();
objC.start();
objC2.start();
objC3.start();
objP2.start();
objP3.start();
}
}
Once again thanks to everyone for your valuable time and suggestions.
Sounds like you are past your initial problem but here's some more feedback.
I believe your real problem was not because of notifyAll() but because your buffer tests were if tests instead of while loops. There are classic race conditions where a thread gets awaken but there are no elements in the buffer. See my notes here. So you code should be something like:
while (Main.itemCount == Main.bufferSize) {
and
while (Main.itemCount == 0) {
Calling notifyAll() exacerbated the problem but the race conditions still exist even with just notify(). As you add more consumers or another producer you will see more problems.
Here is some other feedback.
Be very careful of locks within locks. That is a bad pattern typically and one that I use very infrequently. Do you really need consume() to be synchronized?
Object instance names should start with a lowercase letter so it should be sharedObject.
Any object that you are locking on should be private final if at all possible. You wouldn't want it changing to another object.
Using Main. anything is a bad pattern. How about creating an object with the itemCount and bufferSize and then passing the same instance of that object to all of our producer and consumers? It would also be the object you would lock on.
Be careful of sprinkling your thread code with System.out.println(...) messages as others have recommended. System.out is a synchronized class so this will add locks and memory synchronization that may move or fix the problem. Yes. Debugging threaded programs is hard.
I want to make a test, two thread, one thread is changing the value, another thread use a while to wait the first thread, and then break and finish.But the question is the waiting thread is always running, can' stop any more. Another question is when i open the code of "System.out.println(i + " run");", all the thread can work normally, it's so strange.
import java.util.Date;
public class ThreadTestTwo {
public int a = 0, b = 0,c = 0;
public static void main(String[] args) {
System.out.println(new Date()+"start");
for (int i = 0; i < 100000; i++) {
new ThreadTestTwo().start(i);
if(i % 100000 == 0){
System.out.println(i/100000);
}
}
System.out.println(new Date()+"finish");
}
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
while (true) {
if(c == 1){
b = a;
// System.out.println(i+", set b "+a);
break;
}
// System.out.println(i + " run");
}
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
a = 1;
c = 1;
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
readThread.start();
try {
writeThread.join();
readThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i+" end");
if(b != 1)
throw new RuntimeException("b = "+b);
}
}
The writes of one thread are NOT guaranteed to be seen for another thread unless the variables are marked as volatile or otherwise the transactions need to handled using synchronization or explicit locking
In your case, a,b,c are the instance variables accessed by multiple threads and the reader thread caches the values and so it doesn't see the writer thread's flushed value.
Please refer the below link for more details:
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
I advise you to read more on Threads. Here it is an interesting document from O'really: http://chimera.labs.oreilly.com/books/1234000001805/ch09.html
As for your implementation, you should be aware that the modification of one variable by a thread may not be seen by a reader thread. To combat that either use synchronised gets and sets, access the variables inside a synchronized block, or use an AtomicReference. You could also use a Lock such as ReantrantLock.
Also, if you have two threads, in which the first is waiting for the input of the second, you could use the wait() inside a synchronized block for the first, so that the second could notify() the first one when it finishes its job.
Something like this:
import java.util.Date;
public class ThreadTestTwo {
private int a = 0, b = 0,c = 0;
private final Object lock = new Object();
//Any object is good as a lock, and for a simple case as this it's fine.
//This object will work as a monitor for the synchronized blocks.
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
synchronized ( lock ) {
try {
while( c != 1 ) {
lock.wait();
}
}
catch ( InterruptedException ex ) {
//Exception handling
}
b = a;
}
//System.out.println(i + " run");
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
synchronized ( lock ) {
a = 1;
c = 1;
lock.notify();
}
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
readThread.start();
System.out.println(i+" end");
}
public static void main(String[] args) {
System.out.println(new Date()+"start");
for (int i = 0; i < 100000; i++) {
new ThreadTestTwo().start(i);
if(i % 100000 == 0){
System.out.println(i/100000);
}
}
System.out.println(new Date()+"finish");
}
}
I would say you don't need join() with this method. But if want to wait for the second thread to start after the first is finished, you have to use join() before starting it. Like this:
writeThread.start();
try {
writeThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
readThread.start();
try {
readThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
But if you use join(), for this particular case, I would say you wouldn't need any synchronized blocks or conditions, since the second thread would only start after the death of the first one. Something like this:
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
b = a;
//System.out.println(i + " run");
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
a = 1;
c = 1;
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
try {
writeThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
readThread.start();
try {
readThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
System.out.println(i+" end");
}
I hope I have helped.
Have a nice day. :)
It's not a good idea to use an simple int as a signal between threads because it's not thread safe.
So try to use AtomicInteger instead or make your int volatile and see what will happen.
First of all, this is not a homework.
I have written a piece of code so that:
Thread-1 prints 1,4,7,... (diff is 3)
Thread-2 prints 2,5,8,...
Thread-3 prints 3,6,9,...
And the final output should be:
1,2,3,4,5,6,7,8,9,...
Here's the code that works wonderfully well:
package threadAlgo;
public class ControlOrder {
volatile Monitor monitor = new Monitor();
public static void main(String[] args) {
ControlOrder order = new ControlOrder();
Thread one = new Thread(new Task(order.monitor, 1));
one.setName("Thread-1");
Thread two = new Thread(new Task(order.monitor, 2));
two.setName("Thread-2");
Thread three = new Thread(new Task(order.monitor, 3));
three.setName("Thread-3");
one.start();
two.start();
three.start();
}
}
class Monitor {
int threadNumber = 1;
}
class Task implements Runnable {
private Monitor monitor;
private int myThreadNumber;
private int currentCount;
Task(Monitor monitor, int myThreadNumber) {
this.monitor = monitor;
this.myThreadNumber = myThreadNumber;
this.currentCount = myThreadNumber;
}
#Override
public void run() {
while (true) {
while (monitor.threadNumber != myThreadNumber) {
synchronized (monitor) {
try {
monitor.wait(100); //DOESN'T WORK WITHOUT THE TIMEOUT!!!
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (monitor) {
if (monitor.threadNumber == myThreadNumber) {
System.out.println(Thread.currentThread().getName() + ": " + currentCount);
currentCount = currentCount + 3;
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (myThreadNumber == 3) {
monitor.threadNumber = 1;
} else {
monitor.threadNumber = myThreadNumber + 1;
}
monitor.notifyAll();
}
}
}
}
The only problem is that if I use wait() instead of wait(timeout), then the thread halts.
UPDATE:
Wait condition (while loop) should be inside synchronized block. A lesson for beginners, including me.
You should always
perform notifyAll/notify in conjunction with a change in state.
check the state change before using wait() in a loop.
If you call notify() and no wait() is waiting, then the signal is lost, so unless you check a state change, (or timeout) you can block forever waiting for a signal which doesn't change.
I am trying to learn multi-threading by implementing code snippets. The problem is to distribute cards(52) among four lists using 4 threads(13 each), please suggest better solution or correction in below code.
As this is for practice on multi-threading, I have not made much stress on naming conventions and generics (apologies for this)
import java.util.LinkedList;
import java.util.List;
public class CardsDivideIntoFour {
static final int Max = 52;
static int val = 0;
static Object ox = new Object();
static List list1 = new LinkedList();
static List list2 = new LinkedList();
static List list3 = new LinkedList();
static List list4 = new LinkedList();
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
public void run() {
while (true) {
if (val >= Max) {
break;
}
synchronized (ox) {
list1.add(++val);
System.out.println("a> " + val);
ox.notifyAll();
try {
if (val >= Max) {
// System.out.println("t1 run finished");
// Thread.currentThread().interrupt();
break;
}
Thread.sleep(1000);
ox.wait();
} catch (InterruptedException e) {
}
}
}
// Unreachable code
// System.out.println("t1 run finished");
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
while (true) {
if (val >= Max) {
break;
}
synchronized (ox) {
list2.add(++val);
System.out.println("b> " + val);
ox.notifyAll();
try {
if (val >= Max) {
break;
}
Thread.sleep(1000);
ox.wait();
} catch (InterruptedException e) {
}
}
}
}
});
Thread t3 = new Thread(new Runnable() {
public void run() {
while (true) {
if (val >= Max) {
break;
}
synchronized (ox) {
list3.add(++val);
System.out.println("c> " + val);
ox.notifyAll();
try {
if (val >= Max) {
break;
}
Thread.sleep(1000);
ox.wait();
} catch (InterruptedException e) {
}
}
}
}
});
Thread t4 = new Thread(new Runnable() {
public void run() {
while (true) {
if (val >= Max) {
break;
}
synchronized (ox) {
list4.add(++val);
System.out.println("d> " + val);
ox.notifyAll();
try {
if (val >= Max) {
break;
}
Thread.sleep(1000);
ox.wait();
} catch (InterruptedException e) {
}
}
}
}
});
t1.start();
t2.start();
t3.start();
t4.start();
try {
t1.join();
t2.join();
t3.join();
t4.join();
} catch (Exception e) {
}
System.out.print("List1 has > ");
for (Object o : list1) {
System.out.print((Integer) o + ",");
}
System.out.println("");
System.out.print("List2 has > ");
for (Object o : list2) {
System.out.print((Integer) o + ",");
}
System.out.println("");
System.out.print("List3 has > ");
for (Object o : list3) {
System.out.print((Integer) o + ",");
}
System.out.println("");
System.out.print("List4 has > ");
for (Object o : list4) {
System.out.print((Integer) o + ",");
}
}
}
Why re-inventing the wheel? The new Java SE 7 provides the Fork\Join framework, which does this job for you concurrently.
What about adding a field indicating the current turn of thread?
static int turn = 0;
Take a look at the code.
Details of synchronization
There are three parts of thread synchronization.
1) First, the thread must aquire the lock at synchronized (ox). The thread is being in the blocking state, until the holder thread releases the lock, then the thread attempts to aquire the lock. If it fails again to aquire the lock, it is put again in blocking state.
2) When the thread aquire the lock and enter the block of synchronized, it must firstly determine whether it is really able to aquire the lock or wait for some operation to be done. Thus we have a loop to check if the turn is the thread's turn. If it is not, the thread puts itself in the wait state, saying "I must wait for the one that has the turn to complete its task". The thread then remains in the waiting state, until another thread awakes it with notifyAll. It then re-determine whether it is able to do the job, if not, it puts itself again in waiting state. Otherwise, it does its job.
3) At final, the thread doesn't forgest to wake up the other waiting threads using notfiyAll after finishing its task. If it forgets, the other threads will still in waiting state for ever. This state is called deadlock and may cause the program to hung up.
MI have a program that starts with for loop and it spins for 10 times, and one loop lasts one second. I need to handle a signal (CTRL+C) and while handling it, it should do it's own for loop, and after it stops, then I should return to the main loop. I've managed to do almost everything above, but the loops don't execute separately. They do it parallel. Hope you can help... thanks :)
BTW, my code is:
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class MySig {
public static void shhh(int s){ //s -> seconds :)
s = s*1000;
try{
Thread.sleep(s);
}catch(InterruptedException e){
System.out.println("Uh-oh :(");
}
}
public static void main(String[] args){
Signal.handle(new Signal("INT"), new SignalHandler () {
public void handle(Signal sig) {
for(int i=0; i<5; i++){
System.out.println("+");
shhh(1);
}
}
});
for(int i=0; i<10; i++) {
shhh(1);
System.out.println(i+"/10");
}
}
}
Right, according to the docs, SignalHandler is executed in a separate thread:
...when the VM receives a signal, the special C signal handler creates a
new thread (at priority Thread.MAX_PRIORITY) to run the registered
Java signal handler..
If you want to stop your main loop while the handler is executing, you can add a locking mechanism, something like this:
private static final ReentrantLock lock = new ReentrantLock(true);
private static AtomicInteger signalCount = new AtomicInteger(0);
public static void shhh(int s) { // s -> seconds :)
s = s * 1000;
try {
System.out.println(Thread.currentThread().getName() + " sleeping for "
+ s + "s...");
Thread.sleep(s);
} catch (InterruptedException e) {
System.out.println("Uh-oh :(");
}
}
public static void main(String[] args) throws Exception {
Signal.handle(new Signal("INT"), new SignalHandler() {
public void handle(Signal sig) {
// increment the signal counter
signalCount.incrementAndGet();
// Acquire lock and do all work
lock.lock();
try {
for (int i = 0; i < 5; i++) {
System.out.println("+");
shhh(1);
}
} finally {
// decrement signal counter and unlock
signalCount.decrementAndGet();
lock.unlock();
}
}
});
int i = 0;
while (i < 10) {
try {
lock.lock();
// go back to wait mode if signals have arrived
if (signalCount.get() > 0)
continue;
System.out.println(i + "/10");
shhh(1);
i++;
} finally {
// release lock after each unit of work to allow handler to jump in
lock.unlock();
}
}
}
There might be a better locking strategy.