As in the subject do I correctly shutdown these simultaneous threads?
I assigned a volatile field and check it repeatedly in while loop.
Is there alternative way to do it(like using synchronize or wait() method), please show me.
EDIT I edited code. Is there any way of checking if Thread is alive by different method thatn isAlive();?
Perhaps:
boolean isAlive(){
return running;
}
import javax.swing.JOptionPane;
public class Wat extends Thread {
private char c;
private int interv;
private volatile boolean running = true;
Object synchObj;
public Wat(char c, int interv) {
this.c = c;
this.interv = interv;
synchObj = new Object();
}
public void run() {
while (running) {
synchronized (synchObj) {
try {
showChar(c);
synchObj.wait(interv * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public synchronized static void showChar(char c) {
System.out.println(c);
}
public void shutdown() {
running = false;
synchronized (synchObj) {
synchObj.notify();
}
}
public static void main(String[] args) throws InterruptedException {
Wat w1 = new Wat('A', 3);
Wat w2 = new Wat('B', 4);
Wat w3 = new Wat('C', 5);
w1.start();
w2.start();
w3.start();
Object[] options = { "Shutdown A", "Shutdown B", "Shutdown C" };
int option;
while (w1.isAlive() || w2.isAlive() || w3.isAlive()) {
option = JOptionPane.showOptionDialog(null,
"Which one would you like to shut?", "Threads",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, null, options, options[2]);
switch (option) {
case JOptionPane.YES_OPTION:
w1.shutdown();
break;
case JOptionPane.NO_OPTION:
w2.shutdown();
break;
case JOptionPane.CANCEL_OPTION:
w3.shutdown();
break;
}
Thread.sleep(1);
}
}
}
Your code will probably work fine, but the Thread.sleep is not very elegant. I would do something along these lines, calling the shutdown() method to quit the thread
Object synchObj = new Object();
public void run() {
while (running) {
synchronized (synchObj) {
try {
System.out.println(new Date());
synchObj.wait(5000);
} catch (InterruptedException e) {
// error handling
}
}
}
}
public void shutdown() {
running = false;
synchronized (synchObj) {
synchObj.notify();
}
}
public static void main(String[] args) throws InterruptedException,
IOException {
ThreadTest test = new ThreadTest();
test.start();
BufferedReader tReader = new BufferedReader(new InputStreamReader(
System.in));
tReader.readLine();
test.shutdown();
}
EDIT added test code
Yes, you are closing the threads correctly. The only comment is that you are breaking the encupsulation here because the flag running is accessed directly. I'd recommend you to add method shutdown() that changes this flag to false.
EDIT.
I have just noticed that you are calling sleep() inside the loop. This is indeed bad practice in most cases. You should probably call wait(timeout). In this case your shutdown() method will change the flag to false and then call notify() on same monitor. This will cause your thread to exit immediately.
It seems the program is perfect, uses volatile boolean variable and makes it false.
synchronized need only multi thread access. instead of sleep you can use wait, it has a object access rather than static sleep, also any time you can interrupt the waiting.
Related
Could someone please tell me how to stop a thread if I have the following structure?
I want to stop the thread B after it expires thread C.
c = new c();
c.start();
b = new b();
b.start();
class c extends Thread {
#Override
public void run() {
// DRAW IMAGE
// b.stop(); - doenst work
}
}
class b extends Thread {
#Override
public void run() {
// PROGRESS BAR
}
}
There is no good way to stop a thread instantly.
There is Thread.stop(), but it is dangerous and deprecated. Don't use it unless you have thoroughly analyzed your code and determined that the risks are acceptable.
There is Thread.interrupt(), but there is no guarantee that the thread will stop quickly, or even stop at all.
For Example:
while (!Thread.interrupted()) {
try {
//do stuff
} catch (InterruptedException e) {
// end up
}
}
There is the approach of writing the thread to periodically check a flag, but if the flag is not checked frequently (by accident or by design), then the thread won't stop quickly.
Please Refer to this for more details
Don't use .stop() use interrupt() instead
You need to check periodically in your b thread if it gets interrupted, if interrupted , you can take proper actions -
if(b.isInterrupted()){
//end your work
}
---> http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
Don't use Thread.stop() method, It's already deprecated, in this case you can handle the stopping of the b thread in your code.
For example:
class b extends Thread {
private volatile boolean stopped = false;
public void stop () {
stopped = true;
}
#Override
public void run() {
// PROGRESS BAR
while ( ! stopped ) {
// paint the progress bar
}
}
}
You might want to take a look at this. You can use a flag or just use Thread.currentThread().interrupt(), you can check if a thread is interrupted by calling Thread.isInterrupted() on it.
The solution to this is explained quite well here. Any thread that might need a status flag for shutdown could have the following structure:
volatile boolean shutdownRequested;
...
public void shutdown() { shutdownRequested = true; }
public void doWork() {
while (!shutdownRequested) {
// do stuff
}
}
Thus, in your case, your class B would look similar to the above. And then, in class C, you can call the shutdown() method of class B.
create a lockable object in your calling code
Boolean canRun = true;
c = new c();
when b has finished set canRun to false
periodically check value of canRun in c
Well, try this :
while(true) {
if (!c.isAlive() && b.isAlive()){
b.interrupt();
}
}
Try something like
private void startActionPerformed(java.awt.event.ActionEvent evt) {
p=new Progress();
myThread=new Thread(p);
p.setLocationRelativeTo(null);
p.setVisible(true);
myThread.start();
}
private void stopActionPerformed(java.awt.event.ActionEvent evt) {
if(myThread!=null){
p.Terminate();
try {
myThread.join();
} catch (InterruptedException ex) {
Logger.getLogger(ClassA.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
////////////////////////////////////////////////////////////////
How it Works and Stopped!
int i;
volatile boolean running=true;
public void run(){
while(running){
for(i=0;i<=100;i++){
pro.setValue(i);
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(Progress.class.getName()).log(Level.SEVERE, null, ex);
return;
}
if(i==100){
Terminate();
break;
}
}
}
}
public void Terminate(){
running=false;
}
/////////////////////////////////////////////////////////////////////
Use a Boolean flag.
For Thread safety, use AtomicBoolean.
AtomicBoolean running = new AtomicBoolean(Boolean.TRUE);
In your run() method check this flag in a while condition:
public void run(){
while(running){
...
}
}
When you want to stop this Thread, change the running to false
I am making a Java app which does something on a HotKey combination. I have an infinite while loop to wait for HotKey input to close, but it makes the app very CPU time costing.
Following is how my code looks in the simplest way:
static boolean isOpen = true;
void main()
{
....
add SomeHotKeyListener();
....
while(isOpen)
{ }
releaseResources();
}
void onHotKey(int hotKeyIdentifier)
{
if(hotKeyIdentifier == something)
do something;
if(hotKeyIdentifier == something)
isOpen = false;
}
I need a multi-threading approach to achieve this, or if someone has something better to fit in.
I recommend you read about the synchronized keyword in Java. Just Google it, and you should find a ton of examples and tutorials.
This should solve your case:
static boolean isOpen = true;
static Object lock = new Object();
void main()
{
....
add SomeHotKeyListener();
....
synchronized(lock)
{
while(isOpen)
{
try {
lock.wait()
} catch(InterruptedException e) {
}
}
}
releaseResources();
}
void onHotKey(int hotKeyIdentifier)
{
if(hotKeyIdentifier == something)
do something;
if(hotKeyIdentifier == something)
{
synchronized(lock)
{
isOpen = false;
lock.notify();
}
}
}
Infinite while loop can consume quite a lot of system resource. Using wait and notify is recommended. Also you have to declare your boolean volatile as otherwise there is no guarantee that the changes made by one thread is picked up by the other. Below is an example which does something in a separate thread and until interrupted by the calling thread based on a user input (an enter in this case). See also the example from Oracle here
import java.util.Scanner;
public class WaitTest implements Runnable {
private volatile boolean shutdown = false;
public static void main(String[] args) {
WaitTest w = new WaitTest();
new Thread(w).start();
System.out.println("Press any key to interrupt");
Scanner sc = new Scanner(System.in);
sc.nextLine();
w.triggerShutDown();
}
#Override
public void run() {
while (!shutdown) {
synchronized (this) {
try {
System.out.println("doing some silly things");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Server shutdown successfully");
}
public synchronized void triggerShutDown() {
this.shutdown = true;
notify();
}
}
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 can't figure out what is the problem in the following code:
I have a thread that can be suspended and resumed
Code bellow:
public class CustomThread implements Runnable {
private volatile boolean stop;
private volatile boolean suspend;
String[] names = new String[]{
"A", "B","C","D","E", "F", "G","H","I","J","K", "L"
};
public CustomThread(){
Collections.shuffle(Arrays.asList(names));
System.out.println("Available names:");
System.out.println(Arrays.asList(names));
}
#Override
public void run() {
while(!stop){
synchronized (this) {
if(suspend){
try {
System.out.println("Got suspended");
wait();
System.out.println("Resumed");
} catch (InterruptedException e) {
System.out.println("Got interupted");
}
}
else System.out.println("Suspend false");
}
int randomIdx = new Random().nextInt(names.length);
System.out.println(names[randomIdx]);
}
}
public synchronized void suspend(){
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>Suspend true");
suspend = true;
}
public synchronized void resume(){
suspend = false;
notify();
}
}
I run the following simple code:
public class CustomTest {
/**
* #param args
* #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
CustomThread c = new CustomThread();
Thread t = new Thread(c);
t.start();
Thread.sleep(5000);
System.out.println("++++++++++++++++++++++++++++++++");
c.suspend();
}
}
What I am expecting to see is:
Thread custom runs, main sleeps, main suspends the custom thread by c.suspend() and since main terminates and noone resumes the thread, the thread remains in wait state.
But what I see instead is that the CustomThread prints continually Suspend false and an element from names.
What is the problem here? It is like the Thread.sleep(5000) and c.suspend() in main don't do anything.
The code is fine as written, but your problem is probably that you are running this through Eclipse and you are overwhelming the console. Put a shorter delay in main and you'll see good results.
Note: your suspend method doesn't need to be synchronized as it only writes to a volatile variable.
Instead of if(suspend) you should have while(suspend), see the explanation in javadoc here: http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#wait%28%29
From the javadoc of Object.wait():
...interrupts and spurious wakeups are
possible, and this method should always be used in a loop
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.