Recently I have made a code for multithread exercise, and found something wrong on it.
public class MultiThread {
public static void main(String[] args) throws InterruptedException {
Thread t=new MyMultiThread("Thread1");
Thread t1=new MyMultiThread("Thread2");
Thread t2=new MyMultiThread("Thread3");
t.start();
t1.start();
t2.start();
}
}
class MyMultiThread extends Thread {
private static int num = 1;
public int count;
public int work;//get thread id
private static int sequence;
public MyMultiThread(String name) {
super(name);
}
#Override
public void run() {
synchronized (this.getClass()) {
work = Integer.parseInt(this.getName().substring(2));//get the final number of thread's name
while (num <= 21) {
while (work != sequence%3+1 ) {
this.getClass().notifyAll();
try {
this.getClass().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++;
System.out.println(getName() + ":" + num++);
if (count == 3) {
count = 0;
sequence++;
this.getClass().notifyAll();
try {
this.getClass().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
this.getClass().notifyAll();
}
}
}
First my java version is 13,and found my code doesn't run properly. It seems that my code didn't have any logical problems on it, but there's always has one thread that might not be notified, which makes my code in a error sequence. So I changed my java version from 13 to 14, 11LTS, and finally solved the problem with java 8. But why? I didn't see any update in wait() or notify() method, that made me confused for days.
Related
I'm writing a simple program.
A thread will run infinitely printing, say counting :
class MyThread extends Thread {
private int count = 0;
public void run() {
while(true) {
System.out.println(count++);
try { currentThread().sleep(2000); }
catch (InterruptedException ignored) { }
}
}
}
until user gives any (String) input of more than 2 letters :
class MyThreadStopper extends Thread {
MyThread obj ;
MyThreadStopper(MyThread obj) {
this.obj = obj;
}
public void run() {
String userInput ;
while(true) {
userInput = (new Scanner(System.in)).next();
if( userInput.length() > 2) {
obj.interrupt();
currentThread().interrupt();
}
try{ currentThread().sleep(1000); }
catch (InterruptedException ignored) { }
}
}
}
Used one thread for printing and another thread of different class to get input. I'm not sure where i am doing it wrong.
class temp {
public static void main(String[] args) {
MyThread obj = new MyThread();
MyThreadStopper objStop = new MyThreadStopper(obj);
obj.start();
objStop.start();
}
}
As it keeps printing infinitely, even though i tried printing the userInput and removing if after the userInput.
you are ignoring the interrupt:
you could stop the thread when it is interrupted (or do something else, depeding on the requirements)
class MyThread extends Thread {
private int count = 0;
public void run() {
while(!interrupted) {
System.out.println(count++);
try { currentThread().sleep(2000); }
catch (InterruptedException e) {
// we got interrupted, time to do something
interrupted = true;
}
}
}
}
generally interrupting a thread to stop it is rarely a good solution.
class MyThread extends Thread {
private int count = 0;
public void run() {
while(true) {
System.out.println(count++);
try { currentThread().sleep(2000); }
catch (InterruptedException ignored) {
System.out.println("Interrupted");
break;
}
}
}
}
You were not doing anything once you are catching InterruptedException. So loop was continuing. The above modified code should print "Interrupted" & break.
Im having problems with my Printer-Counter School Problem. Its supposed to be a multithreading application and runs fine so far. But when I running it the second or third time it wont work anymore.. No error message. Looks like Threads sleep forver or so. Also when I test it with a JUnit test it wont work. But sometimes it does... wich is already strange itself.
public class CounterPrinter {
public static void main(String[] args) throws InterruptedException {
if (args.length != 2) {
System.out.println("Usage: CounterPrinter <min> <max>");
System.exit(1);
}
Storage s = new Storage();
Printer d = new Printer(s, Integer.parseInt(args[1]));
Counter z = new Counter(s, Integer.parseInt(args[0]), Integer.parseInt(args[1]));
z.start();
d.start();
z.join();
d.join();
Thread.sleep(5000);
}
}
public class Printerextends Thread {
private Storage storage;
private Integer ende;
Printer(Storage s, Integer ende) {
this.storage = s;
this.ende = ende;
}
#Override
public void run() {
while (storage.hasValue()) {
try {
System.out.print(speicher.getValue(ende) + " ");
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Counter extends Thread {
private Storage speicher;
private int max, min;
Counter(Storages, int min, int max) {
this.storage = s;
this.max = max;
this.min = min;
}
#Override
public void run() {
for (int i = min; i <= max; i++) {
try {
storage.setValue(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Storage implements StorageIf {
private Integer wert;
private boolean hasValue = false;
#Override
public synchronized Integer getValue(Integer ende) throws InterruptedException {
if(wert.equals(ende)){
hasValue = false;
return wert;
}else {
while (!hasValue()) {
wait();
}
hasValue = false;
notifyAll();
return wert;
}
}
#Override
public synchronized void setValue(Integer wert) throws InterruptedException {
while (hasValue()){
wait();
}
hasValue = true;
this.wert = wert;
notifyAll();
}
#Override
public boolean hasValue() {
return hasValue;
}
}
Hope someone can spot a mistake I made :(
Thanks a lot!!!
The problem is that you conflate 2 states :
there is currently a value available
there will be no more values
Add an hasEnded() method to your Storage class, checking if the end value has been reached. Make sure to synchronize this method, as well as the hasValue() method. Synchronization needs to be done on both read and write access!
Then make Printer's while loop check hasEnded, rather than hasValue.
Finally : get rid of all the sleep() calls.
Your own answer, solving the problem with sleep, is not a real solution. A thread safe program does not depend on a computer's performance to function correctly.
z.start();
z.sleep(100);
d.start();
Putting a delay between starting the tow Threads solved the problem for me. My Computer was probably too fast down the road in Thread z before it even started Thread d. Thats why it hung itself up in 50% of the time.
Thanks to everyone tho :)
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.
Essentially, what I want to do is start all my threads, pause them all, then resume them all, using the multithreading approach. I am just looking for a simple solution to this. I'm not sure if I have to use a timer or what. Right now when I run it, the threads are like being executed in random order (I guess the PC is just randomly picking which ones it wants to run at a certain time).
class ChoppingThread extends Thread
{
public void run()
{
for(int j=40;j!=0;j-=10)
System.out.println("Chopping vegetables...("+j+" seconds left)");
}
}
class MixingThread extends Thread
{
public void run()
{
for(int k=60;k!=0;k-=10)
System.out.println("Mixing sauces...("+k+" seconds left)");
}
}
class TenderizingThread extends Thread
{
public void run()
{
for(int j=50;j!=0;j-=10)
System.out.println("Tenderizing meat...("+j+" seconds left)");
}
}
class MultiThreadTasking
{
public static void main (String [] args)
{
ChoppingThread ct = new ChoppingThread();
MixingThread mt = new MixingThread();
TenderizingThread tt = new TenderizingThread();
System.out.println("\nWelcome to the busy kitchen.");
//putting threads into ready state
ct.start();
mt.start();
tt.start();
}
}
There are probably other ways to achieve the same result, but this is the simplest I can come up with off the top of my head (I know, sad isn't it)...
Basically, this is a special Runnable with some additional management functionality.
This basically contains a state flag that indicates the state of the task and a monitor lock
public class ThreadFun {
public static void main(String[] args) {
MyTask task = new MyTask();
Thread thread = new Thread(task);
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
task.pauseTask();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
task.resumeTask();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
task.stopTask();
}
public enum TaskState {
Running,
Stopped,
Paused
}
public static class MyTask implements Runnable {
private static final Object PAUSED_LOCK = new Object();
private volatile TaskState state = TaskState.Running;
public void pauseTask() {
if (state == TaskState.Running) {
System.out.println("Paused...");
state = TaskState.Paused;
}
}
public void resumeTask() {
if (state == TaskState.Paused) {
state = TaskState.Running;
synchronized (PAUSED_LOCK) {
PAUSED_LOCK.notifyAll();
}
System.out.println("Resumed...");
}
}
public void stopTask() {
if (state == TaskState.Running || state == TaskState.Paused) {
state = TaskState.Stopped;
System.out.println("Stopped...");
}
}
public boolean isStopped() {
return state == TaskState.Stopped;
}
public boolean isPaused() {
return state == TaskState.Paused;
}
protected void doPause() {
synchronized (PAUSED_LOCK) {
while (isPaused()) {
try {
PAUSED_LOCK.wait();
} catch (InterruptedException ex) {
}
}
}
}
#Override
public void run() {
int index = 0;
while (!isStopped() && index < 1000) {
try {
Thread.sleep(25);
} catch (InterruptedException ex) {
}
doPause();
index++;
System.out.println(index);
}
stopTask(); // Make sure the task is marked as begin stopped ;)
}
}
}
The main criteria is you will need to pool isStopped and doPause at appropriate points to ensure that they are begin implemented as required...
To coordinate them use a CyclicBarrier.
To launch them all at the same time use a CountDownLatch.
Google the two classes above for many examples and explanations.
To fully understand what is happening read the Java Concurrency In Practice book.
I believe you can accomplish this by using Object.wait and Thread.interrupt.
Object.wait blocks until notify is called. So
private boolean paused;
private Object waitObject;
...
public void run() {
for ... {
if (this.paused) { this.waitObject.wait(); }
...
public void pause() { this.paused = true; }
public void resume() { this.paused = false; this.waitObject.notify(); }
Then you can call pause to pause the thread.
Thread.interrupt can help with stopping.
private boolean paused;
...
public void run() {
for ... {
// interrupted() is different from interrupt()!
if (this.iterrupted()) { break; }
...
To stop it, you would call interrupt() from another thread.
This is the basic idea, but there's a lot of details to worry about here. For example, wait can throw an InterruptedException you'll need to handle. Also, wait is not guaranteed to return only after a notify. It can return randomly. Here is a pair of tutorials:
Wait: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
Interrupt: http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
I'm testing a Java multi-threading sample code but the thread started in the for loop of qB.start() is blocked because it's waiting for entry of qB monitor. What is the cause of this blockage?
Thank you.
import java.util.*;
class QA {
public synchronized void open() throws Exception {
Thread o = new Thread() {
public void run() {
QB qB = new QB();
qB.start();
}
};
o.start();
}
public static void main(String args[]) throws Exception {
new QA().open();
}
public class QB {
private boolean shutdown;
private Vector<Thread> tList;
private final Object waitingLock = new Object();
public QB() {
tList = new Vector<Thread>();
}
public synchronized void start() {
for(int i = 0; i < 1; i++) {
final int id = i;
Thread t = new Thread("Thread " + id) {
public void run() {
load(id);
}
};
tList.add(i, t);
t.start();
}
tMonitor();
waitUntilFinished();
}
private void tMonitor() {
Thread cmt = new Thread("T Monitor Thread") {
public void run() {
synchronized(waitingLock) {
while(tList.size() > 0) {
try {
sleep(10000);
} catch(Exception e) {
e.printStackTrace();
}
}
waitingLock.notifyAll();
}
}
};
cmt.start();
}
private void waitUntilFinished() {
synchronized(waitingLock) {
while(!isShutDown()) {
try {
waitingLock.wait();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
private synchronized void load(int id) {
try {
System.out.println("blocked here");
// some work done here
removeFromTList(id);
} catch(Exception e) {
e.printStackTrace();
}
}
public synchronized boolean isShutDown() {
return shutdown;
}
}
}
The first problem I see is that QB#start() is synchronized on the instance of QB.
Inside the thread t that you are trying to spawn, load(id) is also synchronized on the same instance of QB. So when you call t.start() the t thread blocks until QB#start() finishes.
Presumably, at the end of the QB#start() method, QB#waitUntilFinished() is supposed to wait for all the t threads to finish, but they can't even enter the QB#load method because they're still waiting for the QB#start() method to release the lock on the QB instance.
So, circular deadlock.
Edit:
Ok, now that we see how the threads are removed from tList the bug is fully revealed.
If the index 0 thread finishes first then it will remove itself from the list. That means when the index 1 thread finishes, it will remove the 1th position from the Vector but that does not point to itself anymore. It is removing the #2 thread. Sooner or later you are going to get an exception when the remove happens because it is going to be removing an invalid index.
You need to remove items from the Vector by address and not by position:
tList.remove(this);
That will remove the current thread from the list. You should also just do an add(t) instead of an add(i t) in the start loop:
tList.add(t);
You now don't need the id position passed into your thread at all.
I don't see where you are removing the finished threads from your tList. I see a definition (not that you edited your OP) of a removeFromTList() method but I don't see it used anywhere. In tMonitor you are in a while loop here:
while(tList.size() > 0) {
try {
sleep(10000);
} catch(Exception e) {
e.printStackTrace();
}
}
// you never get to this line
waitingLock.notifyAll();
But I don't see anything that removes the thread from the list. Maybe when the threads each finish they are supposed to remove themselves?
If tMonitor thread never gets out of that loop then it never calls:
waitingLock.notifyAll();
So the main thread will hang forever in waitUntilFinished();.
synchronized(waitingLock) {
while(!isShutDown()) {
try {
waitingLock.wait();
} catch(Exception e) {
e.printStackTrace();
}
}
Also, you don't want to do a sleep in tMonitor() because you are in a synchronized block. You should be doing a:
waitingLock.wait(10000);
Nothing will ever notify it but it's bad form to hold the lock like that in a sleep.