I am currently working on a project where I am to have essentially 10 threads that are "sleeping". At random one of these 10 threads is to "wake up" and start doing some work. I just want to see if I am headed in the right direction. So should I just create each instance of the thread for instance.
Thread thread0 = new Thread(new doWork());
...
Thread thread9 = new Thread(new doWork());
and just not start them and then when they are to "wake" just call the start() method on the particular thread..
or should I start each thread but have them wait() until I call the notify() method?
or should I start the thread and use sleep() and then call the interrupt() method?
Which approach seems to be better and why?
Any insight is greatly appreciated.
edit Will this be acceptable??
import java.util.Random;
public class Client {
private static Thread [] clients = new Thread[10];
public static void main(String[] args){
createClients();
randomWake();
}// end main()
static void createClients(){
Thread client0 = new Thread(new ClientThread(0));
clients[0] = client0;
Thread client1 = new Thread(new ClientThread(1));
clients[1] = client1;
Thread client2 = new Thread(new ClientThread(2));
clients[2] = client2;
Thread client3 = new Thread(new ClientThread(3));
clients[3] = client3;
Thread client4 = new Thread(new ClientThread(4));
clients[4] = client4;
Thread client5 = new Thread(new ClientThread(5));
clients[5] = client5;
Thread client6 = new Thread(new ClientThread(6));
clients[6] = client6;
Thread client7 = new Thread(new ClientThread(7));
clients[7] = client7;
Thread client8 = new Thread(new ClientThread(8));
clients[8] = client8;
Thread client9 = new Thread(new ClientThread(9));
clients[9] = client9;
for(int i = 0; i < clients.length; i++)
clients[i].start();
}// end createClients()
static void randomWake(){
Random rand = new Random();
int randomNumber = rand.nextInt(10);
clients[randomNumber].interrupt();
}// end randomWake()
static class ClientThread implements Runnable{
private int clientNumber;
public ClientThread(int clientNumber){
this.clientNumber = clientNumber;
}// end ClientThread(int clientNumber)
public void run(){
while(!Thread.interrupted()){}
System.out.println("Client " + clientNumber + " is awake!");
}// end run()
}// end class ClientThread
}// end class Client
In case there is a maximum amount of sleep time
You probably will need to implement the following Thread class:
public class DoWork extends Thread {
public void run () {
while(true) {
Thread.Sleep((int) Math.floor(Math.random()*10000));
//do some work
}
}
}
Where 10000 is the maximum time in milliseconds a thread should sleep.
In case there is no maximum amount of sleep time
You probably will need to implement the following Thread class:
public class DoWork extends Thread {
public void run () {
while(true) {
Thread.Sleep(1);
if(Math.random() < 0.005d) {
//do some work
}
}
}
}
where 0.005 is the probability of running the method a certain millisecond.
notify and wait are used to implement Semaphores: this are objects that prevent two threads to manipulate the same object at the same time (since some objects could end up in an illegal state).
How about using semaphores?
class DoWork extends Runnable {
private final Semaphore semaphore;
DoWork(Semaphore semaphore) {
this.semaphore = semaphore;
}
#Override
public void run() {
while (true) {
semaphore.acquire();
//do some work
}
}
}
The main program can create an array of Semaphores, and an equal number of Threads running DoWork instances, so that each DoWork instance has its own semaphore. Each time the main program calls sema[i].release(), The run() method of the corresponding DoWork instance will "do some work" and then go back to waiting.
It doesn't make much sense your answer, so not sure what you really want to achieve. But for what you describe you should put all threads waiting on the same lock and just notify the lock (it will awake only one randomly)
But as that doesn't make much sense, I guess you want to achieve something different.
Check this question regarding sleep vs wait: Difference between wait() and sleep()
Check this one. This is how I would solve it if I were not to use ThreadPooling (which is very correct as the others have said) and so that I can see how wait(),notify() and Thread.sleep() work. Checking google you will see (e.g. Thread.sleep and object.wait) that the mainly wait() and notify() are used for communication between threads and Thread.sleep is used so that you can pause your program.
-Part of this answer is based on this: http://tutorials.jenkov.com/java-concurrency/thread-signaling.html#missedsignals. You can check in the code to see the steps that you need to take (comment out some parts of the code) in order to make your program hang, so that you realize how to work with missed signals. The iterations needed for your program to hang are not fixed.
-The programm will run forever. You will need to work on it a bit in order to fix that.
Main
public class Main
{
public static void main(String[] args)
{
Manager mgr = new Manager("manager");
mgr.start();
}
}
Manager
public class Manager extends Thread
{
private final Object lock = new Object();
private boolean wasSignalled = false;
private DoWork[] workThreads = new DoWork[5];
public Manager(String name){
super(name);
workThreads[0] = new DoWork(this,"work 0");
workThreads[1] = new DoWork(this,"work 1");
workThreads[2] = new DoWork(this,"work 2");
workThreads[3] = new DoWork(this,"work 3");
workThreads[4] = new DoWork(this,"work 4");
}
public void wakeUP()
{
synchronized (this.lock) {
wasSignalled = true;
this.lock.notify();
}
}
public void pauseAndWait()
{
synchronized (this.lock) {
if(!wasSignalled)
{
try {
this.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//clear signal and continue running.
wasSignalled = false;
}
}
public void run ()
{
int i=0;
while(true)
{
i++;
System.out.println(" manager ...: "+i+" ");
int choose = 0 + (int)(Math.random() * ((4 - 0) + 1));
//choose=0; for debugginng
if(!workThreads[choose].isAlive()){
workThreads[choose].start();
}
else{
workThreads[choose].wakeUP();
}
//wait to be notified by DoWork thread when its job
//is done
pauseAndWait();
}
}
}
DoWork
public class DoWork extends Thread
{
private final Object lock = new Object();
private boolean wasSignalled = false;
private Manager managerThread;
public DoWork(Manager managerThread,String name){
super(name);
this.managerThread=managerThread;
}
public void wakeUP()
{
synchronized (this.lock) {
//check what happens without wasSignalled flag
//step #1: comment out wasSignalled = true;
wasSignalled = true;
this.lock.notify();
}
}
public void pauseAndWait()
{
synchronized (this.lock) {
//check what happens without wasSignalled flag
//step #2: comment out the if block
if(!wasSignalled)
{
try {
this.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//check what happens without wasSignalled flag
//step #3: comment out wasSignalled = false;
//clear signal and continue running.
wasSignalled = false;
}
}
public void run ()
{
int i=0;
while(true)
{
i++;
try {
System.out.print(this.getName()+" going to sleep ...: "+i+" ");
//check what happens without wasSignalled flag
//step #4: put sleep time to Thread.sleep(0);
//simulate worker thread job
Thread.sleep(1000);
System.out.println(" woke up ... ");
} catch (InterruptedException e) {
System.out.println(" worker thread: job simulation error:"+e);
}
//if worker thread job simulation is done (sleep for 4 times)
//then suspend thread and wait to be awaken again
if(i>4)
{
System.out.println(this.getName()+" notifying main ...: "+i+" \n");
i=0;
managerThread.wakeUP();
// thread does not get destroyed, it stays in memory and when the manager
// thread calls it again it will wake up do its job again
pauseAndWait();
}
}
}
}
Related
Threads are stored in an ArrayList so that they can dynamically be set later on by their name. There are a lot of examples on the Internet, all about this, but I do not work, so the selected thread does not stop.
What can my fault be?
public class Szal {
static ArrayList<MyThread> myThread;
static String[] names;
public Szal() {
myThread = new ArrayList<MyThread>();
names = new String[]{"EZ", "AZ"};
for (int i = 0; i < names.length; i++) {
MyThread t = new MyThread(names[i]);
myThread.add(t);
t.start();
}
}
public static void main(String[] args) {
new Szal();
Thread[] thread = new Thread [Thread.activeCount ()];
int m = Thread.enumerate (thread);
for (int i = 0; i < m; i++) {
System.out.println (thread[i].getName());
}
// Why is this not working?
for (Thread t : myThread) {
if (t.getName().equalsIgnoreCase("EZ")) {
t = Thread.currentThread();
t.interrupt();
myThread.remove(t);
}
}
Thread[] threads = new Thread [Thread.activeCount ()];
int c = Thread.enumerate (threads);
for (int i = 0; i < c; i++) {
System.out.println (threads[i].getName());
}
}
class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
public void run() {
while (true) {
}
}
}
}
//this why not working???
for(Thread t : myThread){
if(t.getName().equalsIgnoreCase("EZ")){
t= Thread.currentThread();
t.interrupt();
myThread.remove(t);
}
}
You iterate over all threads in the list and iterrupt yourself as soon as you reach the one with the name EZ. I'm not sure if that's what you actually planned to do, your question sounded more like you wanted to interrupt the EZ-Thread. In that case you should omit the line t = Thread.currentThread().
You haven't explained what exactly you mean with "not working", I assume that you mean that the thread you interrupted still continues to run. That's because, none of the threads is actually performing an operation that is checking the fact if it's interrupted.
You might change your MyThread-implementation this way:
class MyThread extends Thread{
public MyThread(String name) {
super(name);
}
public void run() {
try {
while(true){
Thread.sleep(10);
}
}
catch(InterrutedException ie) {
// leads to the end of the thread
}
}
}
or alternatively
while(!interrupted()){
}
Oh, and wait a bit between interrupting and outputting all Threads. Starting and shutting down threads is a complex task that takes some time. So even with fully functional code that reliably shuts down your Thread, the interrupted one might still show up as active if you list all threads immediately afterwards.
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 simulate a parking lot entry system that contains 2 floors of 20 spaces and 2 entries and 2 exits. I am using Threads in Java, and I have tried to use thread.wait() and thread.sleep but they don't help in making a thread run after another thread is over.
This is what I have come up with so far:
ShardedDataThread.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class SharedDataThread extends Thread {
private SharedData mySharedData;
private String myThreadName;
public int L1 = 20;
public int L2 = 20;
//Setup the thread
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
SharedDataThread(String name, SharedData sharedstuff) {
super(name);
mySharedData=sharedstuff;
myThreadName=name;
}
//This is called when "start" is used in the calling method
public void run() {
while(true){
System.out.println("Entry or Exit?");
String input = null;
try {
input = br.readLine();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (input.equalsIgnoreCase("entry")) {
try {
// Acquire the lock using the acquireLock() method
// The thread will pause here on wait() until it gets a lock
mySharedData.acquireLock();
//use park method to occupy one space
this.park(); // Increment the number of reads
mySharedData.releaseLock();
}
catch(InterruptedException e) {
System.err.println("Failed to get lock when reading:"+e);
}
}
else {
try {
mySharedData.acquireLock();
System.out.println(myThreadName+" is writing");
exit(); // INCREMENT ONE SPOT
mySharedData.releaseLock(); // releases the lock
}
catch(InterruptedException e) {
System.err.println("Failed to get lock when writing:"+e);
}
}
System.out.println("L1 has : "+L1+" "+"L2 has: "+" "+L2);
}
//while ends
}
//State method
public void park() {
if (L1>0 && L1<=20){
L1= L1-1;
}
else if (L1==0 && L2<=20 && L2>0){
L2= L2-1;
}
else if (L1==0 && L2==0){
System.out.println("No Spaces Left");
}
}
public void exit() {
if (L1<20) {
L1 = L1 +1;
} else if (L2<20) {
L2 = L2+1;
}
}
public static void main(String[] args) throws InterruptedException {
SharedData mySharedData = new SharedData();
SharedDataThread myThread1 = new SharedDataThread("Entry1", mySharedData);
//SharedDataThread myThread2 = new SharedDataThread("Entry2", mySharedData);
//SharedDataThread myThread3 = new SharedDataThread("Exit1", mySharedData);
//SharedDataThread myThread4 = new SharedDataThread("Exit2", mySharedData);
// Now start the threads executing
myThread1.start();
//myThread1.join();
//myThread2.start();
//myThread2.join();
//myThread3.start();
//myThread3.join();
//myThread4.wait();
}
}
SharedData.java
public class SharedData {
private boolean accessing=false; // true a thread has a lock, false otherwise
// attempt to acquire a lock
public synchronized void acquireLock() throws InterruptedException{
Thread me = Thread.currentThread();
while (accessing) {
wait();
}
accessing = true;
}
// Releases a lock to when a thread is finished
public synchronized void releaseLock() {
//release the lock and tell everyone
accessing = false;
notifyAll();
Thread me = Thread.currentThread(); // get a ref to the current thread
}
}
This never makes any sense:
myThread1.start();
myThread1.join();
It never makes any sense to start a thread and then immediately wait for it to finish. The entire point of having threads is that different threads can be doing different things at the same time.
If there isn't anything else that the caller wants to do while myThread1 is running, then there is no reason to create myThread1. The caller should just do whatever it is that myThread1 would have done at that point.
Don't use threads to model objects in a simulation. Use threads to do work. Usually, that means, use a thread pool such as java.util.concurrent.ThreadPoolExecutor to perform tasks.
If you want your simulation to run in real time, don't use threads that sleep(). Use a scheduler such as java.util.concurrent.ScheduledThreadPoolExecutor to perform delayed tasks.
You're thinking about the problem wrong. Don't think about waiting for a thread to do something after a thread is done. Think about doing something after some work is done. That means that the work has to be waitable.
I'm trying to come with a solution for a thread to pause and resume exactly where it was left off.
So here's a sample code emulating my problem: 2 threads are running in the background: taskThread & busyThread. When busyThread is in system is busy area, taskThread must alt/pause immediately and resume exactly where it was left off. Example, if taskThread was paused at task C (finished) it should resume at D.
I tried to use wait, notify on taskThread but without success.
public class Test
{
private Thread taskThread;
private Thread busyThread;
public static void main(String args[]) throws Exception
{
Test t = new Test();
t.runTaskThread();
t.runBusyThread();
}
public void runTaskThread()
{
taskThread = new Thread(new Runnable(){
#Override
public void run()
{
for (int x=0; x<100; x++)
{
try
{
System.out.println("I'm doing task A for process #"+x);
Thread.sleep(1000);
System.out.println("I'm doing task B for process #"+x);
Thread.sleep(200);
System.out.println("I'm doing task C for process #"+x);
Thread.sleep(300);
System.out.println("I'm doing task D for process #"+x);
Thread.sleep(800);
System.out.println("\n\n");
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}});
taskThread.start();
}
public void runBusyThread()
{
busyThread = new Thread(new Runnable(){
#Override
public void run()
{
while (true)
{
Random rand = new Random();
int randomNum = rand.nextInt(1000);
if (randomNum<400)
{
System.out.println("Wait...system is busy!!!");
try
{ //what should come here to to signal taskThread to paused
Thread.sleep(3000);
//what should come here to to signal taskThread to resume
} catch (InterruptedException e)
{
}
} else
{
try
{
Thread.sleep(300);
} catch (InterruptedException e)
{
}
}
}
}});
busyThread.start();
}
}
There are two very useful classes in concurrency package - CountDownLatch and CyclicBarrier. If you need this behaviour only once, you probably want the first one (as it cannot be reset).
Thread 1 will await until notified by thread 2. Once it was counted down to 0, thread 1 will never block again at await():
CountDownLatch cdl = new CountDownLatch(1);
// thread 1:
cdl.await();
// thread 2:
cdl.countDown();
Threads will block at await() until there are exactly two threads waiting:
CyclicBarrier barrier = new CyclicBarrier(2);
// both threads:
barrier.await();
EDIT:
Here is what I came up with when modifying your code, however it is unclear to me whether it is expected behaviour.
Note a volatile keyword on the CountDownLatch - it is very important here, otherwise taskThread may cache the initial object (new CountDownLatch(0)) and hence never block.
public class Test {
private Thread taskThread;
private Thread busyThread;
private volatile CountDownLatch cdl = new CountDownLatch(0);
public static void main(String args[]) throws Exception {
Test t = new Test();
t.runTaskThread();
t.runBusyThread();
}
public void runTaskThread() {
taskThread = new Thread(() -> {
for (int x = 0; x < 100; x++) {
waitIfSystemBusy();
System.out.println("I'm doing task A for process #" + x);
sleep(1000);
waitIfSystemBusy();
System.out.println("I'm doing task B for process #" + x);
sleep(200);
waitIfSystemBusy();
System.out.println("I'm doing task C for process #" + x);
sleep(300);
waitIfSystemBusy();
System.out.println("I'm doing task D for process #" + x);
sleep(800);
System.out.println("\n\n");
}
});
taskThread.start();
}
public void runBusyThread() {
busyThread = new Thread(() -> {
while (true) {
Random rand = new Random();
int randomNum = rand.nextInt(1000);
if (randomNum < 400) {
System.out.println("Wait...system is busy!!!");
cdl = new CountDownLatch(1); // signal taskThread to pause
sleep(3000);
cdl.countDown(); // signal taskThread to resume
} else {
sleep(300);
}
}
});
busyThread.start();
}
private void waitIfSystemBusy() {
try {
cdl.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private static void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
It would be done using the deprecated methods Thread.suspend/resume.
They are deprecated as they are deadlock prone, whereas concurrency mechanisms like locks behave in a designed explicit manner (but still deadlock prone).
I would suggest create a class that implements Runnable which simply keep track of the stages you are in
just as an example (please change accordingly)
class MyRunnable implements Runnable {
private int stage = 0; // if you want it gloabally, then use static
#Override
public void run() {
try{
switch(stage){
case 1:
System.out.println("1");
stage++;
case 2:
System.out.println("2");
Thread.sleep(2000);
stage++;
default:
stage = 0;
}
}catch (Exception e){
}
}
}
now to use such class you just need to create a new thread
for example:
public static void main(String[] args) throws Exception{
MyRunnable myRunnable=new MyRunnable();
new Thread(myRunnable).start(); //it prints 1
Thread.sleep(1000);
new Thread(myRunnable).start(); //prints 2 follow by 2 sec sleep
}
NOTE:
this example wasn't intended to answer the question exactly but rather show a logic how it can be done.
EDIT 1:
what should come here to to signal taskThread to paused
taskThread.interupt();
what should come here to to signal taskThread to resume
taskThread=new Thread(myRunnable);
taskThread.start();
Instead of sleep() I would prefer wait() and notifyAll().
have a Boolean systemBusy, implement get and set methods;
now in thread1
run(){
synchronize(something){
while(isSystemBusy()){
try{
wait();}
catch{}
}
}
}
and on the other thread
run(){
setSystemBusy(true);
//piece of code
//task finished
notifyAll();
setSystemBusy(false);
}
you can use this in multiple waiting threads just remember to set appropriate while condition false after notify all.
The following code was summed up the application, the application randomly was locked in
while (flag)
This code, running on my machine gets caught, in another machine he finished normally
The output generated here is:
INIT
END
before while
before flag
after flag
Code:
package threads;
public class Run implements Runnable {
private Thread thread;
private boolean flag = true;
public void init() {
thread = new Thread(this);
thread.setName("MyThread");
thread.start();
}
#Override
public void run() {
try {
int i = 0;
while (i < 1000) {
i++;
}
System.out.println("before flag");
flag = false;
System.out.println("after flag");
} catch (Exception e) {
e.printStackTrace();
} finally {
flag = false;
}
}
public void end() {
thread.interrupt();
thread = null;
System.out.println("before while");
while (flag) {
// try { Thread.sleep(100);} catch (InterruptedException e) {}
}
;
System.out.println("after while");
}
public static void main(String[] args) {
Run r = new Run();
System.out.println("INIT");
r.init();
System.out.println("END");
r.end();
}
}
Why when I change the value of flag the main thread does not pass through loop?
Change
private boolean flag = true;
to
private volatile boolean flag = true;
Without volatile, there is no guarantee the waiting thread needs to see the value get updated. HotSpot might even inline while(flag) to while(true) if the loop spins enough times.
See Memory Consistency Errors.
Also, what you're doing is called a spinlock. Normally you should use thread.join() instead. A spinlock is wasteful of resources because the waiting thread is actually working (checking a variable) the entire time it is supposed to be waiting.