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.
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 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.
I am new to multithreading, and get to know about the functionality of wait, notify and notifyAll. I want three threads to execute one after another and print alphabets from A to Z.
I have tried below code and it seems working also, but I doubt if this is the best possible way to tackle the problem. Is there any other way, I can make it more simple and better ? It seems some portion of my code is repeating.
package demo.threading;
class Flags {
boolean flagA = true;
boolean flagB = false;
boolean flagC = false;
}
class Container {
Flags flags = new Flags();
int charVal = (int) 'A';
void producer1() {
try {
while (charVal <= (int) 'Z') {
synchronized (this) {
if (!flags.flagA)
wait();
else {
System.out.println(Thread.currentThread().getName() + " Produced : " + (char) charVal);
flags.flagA = false;
flags.flagB = true;
charVal++;
notifyAll();
Thread.sleep(1000);
}
}
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
void producer2() {
try {
while (charVal <= (int) 'Z') {
synchronized (this) {
if (!flags.flagB)
wait();
else {
System.out.println(Thread.currentThread().getName() + " Produced : " + (char) charVal);
flags.flagB = false;
flags.flagC = true;
charVal++;
notifyAll();
Thread.sleep(1000);
}
}
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
void producer3() {
try {
while (charVal <= (int) 'Z') {
synchronized (this) {
if (!flags.flagC)
wait();
else {
System.out.println(Thread.currentThread().getName() + " Produced : " + (char) charVal);
flags.flagC = false;
flags.flagA = true;
charVal++;
notifyAll();
Thread.sleep(1000);
}
}
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
Container container = new Container();
Thread t1 = new Thread(() -> container.producer1(), "Thread 1");
Thread t2 = new Thread(() -> container.producer2(), "Thread 2");
Thread t3 = new Thread(() -> container.producer3(), "Thread 3");
t1.start();
t2.start();
t3.start();
}
}
Output should be :
Thread 1 Produced : A
Thread 2 Produced : B
Thread 3 Produced : C
Thread 1 Produced : D
Thread 2 Produced : E
Thread 3 Produced : F
As pointed out before, if you want to do this "one after another", you actually don't need multiple threads. However, you can achieve this by using a Semaphore:
int numberOfThreads = 3;
Semaphore semaphore = new Semaphore(1);
for (int i = 1; i <= numberOfThreads; i++) {
new Thread(() -> {
try {
semaphore.acquire();
for (char c : "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray()) {
System.out.println(Thread.currentThread().getName()
+ " produced: " + c + ".");
}
} catch (InterruptedException e) {
// NOP
} finally {
semaphore.release();
}
}, "Thread " + i).start();
}
I recommend exploring java.util.concurrent which is available since Java 5. It's a great help to keep your concurrent code concise and simple compared with Java's low-level concurrency primitives such as wait and notify. If you're really interested in that topic, Brian Goetz's "Java Concurrency in Practice" is a must-read.
EDIT:
public class ConcurrentAlphabet {
private volatile Thread current;
public static void main(String[] args) {
new ConcurrentAlphabet().print(3,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray());
}
public void print(int numberOfThreads, char[] alphabet) {
Thread[] threads = new Thread[numberOfThreads];
for (int i = 1; i <= numberOfThreads; i++) {
int offset = i - 1;
threads[offset] = new Thread(() -> {
Thread me = Thread.currentThread();
Thread next = threads[(offset + 1) % numberOfThreads];
for (int index = offset; index < alphabet.length; index += numberOfThreads) {
synchronized (this) {
while (me != current) {
try {
wait();
} catch (InterruptedException e) { /* NOP */ }
}
System.out.println(me.getName() + " produced: " + alphabet[index] + ".");
current = next;
notifyAll();
}
}
}, "Thread " + i);
}
current = threads[0];
for (Thread t : threads) {
t.start();
}
}
}
package demo.thread;
public class ABCPuzzle {
private static class RunnableImpl implements Runnable {
private String nextThread;
private ExecServ execServ;
public RunnableImpl(ExecServ execServ, String nextThread) {
this.execServ = execServ;
this.nextThread = nextThread;
}
#Override
public void run() {
String threadName = Thread.currentThread().getName();
synchronized (execServ) {
try {
while (true) {
if (execServ.key > 'Z')
break;
if (threadName.equals(execServ.current)) {
System.out.println(threadName + " consuming " + execServ.key);
Thread.sleep(1000);
execServ.key++;
execServ.current = nextThread;
execServ.notifyAll();
} else
execServ.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class ExecServ {
private String current, next;
private char key = 'A';
}
public static void main(String[] args) {
ExecServ execServ = new ExecServ();
execServ.current = "t1";
Thread t1 = new Thread(new RunnableImpl(execServ, "t2"), "t1");
Thread t2 = new Thread(new RunnableImpl(execServ, "t3"), "t2");
Thread t3 = new Thread(new RunnableImpl(execServ, "t4"), "t3");
Thread t4 = new Thread(new RunnableImpl(execServ, "t1"), "t4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
Output :
t1 consuming A
t2 consuming B
t3 consuming C
t4 consuming D
t1 consuming E
t2 consuming F
t3 consuming G
t4 consuming H
t1 consuming I
t2 consuming J
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 just write some code to test the multiple threads how to synchronize,but I cannot get my expected result.The code can start 3 threads,but only one thread to process the shared resource.what is wrong with my code.
class ThreadDemo1{
public static void main (String[] args){
MultiThread tt = new MultiThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
class MultiThread implements Runnable {
int tickets = 100;
Object _lock = new Object();
public void run () {
System.out.println(Thread.currentThread().getName());
synchronized(_lock) {
while (true) {
if (tickets>0) {
try {
Thread.sleep(10);
} catch (Exception e) {}
System.out.println(Thread.currentThread().getName() + " is selling "+tickets--);
}
}
}
}
}
You are sleeping while holding the lock. There is no reason to multithread if you are going to do that.
public void run () {
System.out.println(Thread.currentThread().getName());
while(tickets > 0) {
synchronized(_lock) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + tickets--);
}
}
try {
Thread.sleep(10);
} catch (Exception e) {
}
}
}
I'm guessing the sleep was a placeholder for your processing. If possible, you should do the check and decrement inside the synchronized block, but your lengthy processing outside it.
In order for locks and multi-threading to do anything useful for you, you must make sure that your synchronized code takes as little time as possible, since that is the code that can be run by only one thread at a time.
In your code, the only thing that wasn't effectively single-threaded was your first System.println.
FYI, with that in mind, if you could have your print statements accurate but possibly out of order, it would be even better to have:
public void run () {
System.out.println(Thread.currentThread().getName());
while(tickets > 0) {
int oldTickets = 0;
synchronized(_lock) {
if (tickets > 0) {
oldTickets = tickets--;
}
}
if(oldTickets > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + oldTickets);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
}
[1]First, there are several bad practice/mistakes in your posted code:
(1) It's better that the Lock Object to be singleton. You can use an static field object or the Class itself(Since there is only one Class in memory)
Object _lock = new Object();
private static final Object _lock = new Object();
(2) Put the while(true) {...} out of the synchronized block. In your code, if the 1st thread obtains the Lock, it will process ALL the tickets and will not stop.
Should make every thread try to obtain the Lock in each iteration of the loop.
(3) For the Thread.sleep(10), I guess you mean the thread is doing some heavy job. But it's not a good practice to put this kind of code in synchronized block(Or another name: critical region). Because there is only one thread can access the synchronized block at one time. The behavior of you code is like a single thread program, because other threads must wait until the currently running thread finishes its job.
Pls see below code:
public class ThreadDemo1 {
public static void main(String[] args) {
MultiThread tt = new MultiThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
public class MultiThread implements Runnable {
private static int tickets = 100;
private static final Object _lock = new Object();
public void run() {
System.out.println(Thread.currentThread().getName());
while (tickets > 0) {
try {
synchronized (_lock) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + tickets--);
}
}
Thread.sleep(10);
} catch (Exception e) {
}
}
}
}
[2]Second, if you just want to synchronize the threads in picking the tickets. Try to use Atomic* Classes instead of synchronized block, it’s No-lock and will bring you a better performance. Example:
import java.util.concurrent.atomic.AtomicInteger;
public class MultiThreadAtomic implements Runnable {
private static AtomicInteger tickets = new AtomicInteger(100);
public void run() {
System.out.println(Thread.currentThread().getName());
int ticketsRemaining = 0;
while ((ticketsRemaining = tickets.getAndDecrement()) > 0) {
System.out.println(Thread.currentThread().getName() + " is selling " + ticketsRemaining);
try {
Thread.sleep(10);
}
catch(InterruptedException ie) {}
}
}
}