I am having troubles with stopping a thread which is started from outside the class using a actionPerformed on a JButton. Code of the thread class below.
public synchronized void run ()
{
try
{
do
{
int minuta = vrijeme / 60;
int sekundi = vrijeme % 60;
System.out.println(minuta+" "+sekundi);
vrijeme = vrijeme - 1;
delay = delay - 1000;
if (minuta == stani && sekundi == 0)
{
}
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
while (delay != 0);
{
//
}
}
catch (Exception e)
{
System.out.println("Stao" + e);
}
}
void pokreniThread()
{
(new Thread(new OdredenoVrijeme())).start();
}
synchronized public void zaustaviThread()
{
try
{
(new Thread(new OdredenoVrijeme())).wait();
}
catch (Exception e)
{
System.out.println("stao" +e);
}
}
}
Every time i call .sleep() .wait() or anything similar i get the following catch message:
java.lang.IllegalMonitorStateException
Under Java, you cannot have a sleep in the main process. Create a sub-thread, which will do the sleep, then post a message to a handler in the main-thread, to do something after the timeout.
If you want to stop a thread itself, set a variable inside the thread like is_stopping=true, then inside the thread you could set a variable is_running=false after the thread stops itself.
is_running=true;
while (is_running & !is_stopping)
{
do_something();
sleep();
}
is_stopping=false;
is_running=false;
In java the main thread is playing a scheduler part in the program. So in a multithreading situation you have these parts:
scheduler/controller
provider
customer
The main thread should always play the scheduler/controller part of the program. BTW you are not using multithreading in a good way. use synchronized when its absolutely necessary.
look at the following code. you should use synchronization like this:
public class BlockingQueue<T> {
private Queue<T> queue = new LinkedList<T>();
private int capacity;
public BlockingQueue(int capacity) {
this.capacity = capacity;
}
public synchronized void put(T element) throws InterruptedException {
while(queue.size() == capacity) {
wait();
}
queue.add(element);
notify(); // notifyAll() for multiple producer/consumer threads
}
public synchronized T take() throws InterruptedException {
while(queue.isEmpty()) {
wait();
}
T item = queue.remove();
notify(); // notifyAll() for multiple producer/consumer threads
return item;
}
You cannot stop a thread from an external context. The thread should stop itself when some condition changes.
You have to hold a flag in your thread that you want to stop, and the thread to check the flag in a loop. If the flag is changed, then the thread itself should do nothing and it will exit by itself
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 writing Java software, that has a single thread, which listens to external buttons being pressed. If the button is pressed, the thread informs other threads, but otherwise it just sleeps.
My model is to use interrupt-driven design. Ideally I would like to make
a thread sleep as long as no button is pressed. When the button is pressed I would like the thread to do some work and go back to sleep.
Could anyone confirm / correct the following implementation?
// This is a code that interrupt-driven thread will execute
public void run() {
while (true) {
try {
Thread.sleep(1000); // Sleeps only for 1s. How to sleep indefinitely?
} catch (InterruptedException exception) {
process(exception); // Doing some work
// then going back to sleep using the while loop
}
}
}
Also, after each button click in the terminal I get a message
I/O exception raised from stop()
What does this message mean (i.e why is it printed if I catch the exception)? Can I avoid the terminal to print it?
It is generally considered a code smell if you use exceptions to control your program flow.
The correct solution to this problem is to use a BlockingQueue of events that the event handler reads from. This is commonly called a producer/consumer.
public class TwoThreads {
public static void main(String args[]) throws InterruptedException {
System.out.println("TwoThreads:Test");
new TwoThreads().test();
}
// The end of the list.
private static final Integer End = -1;
static class Producer implements Runnable {
final BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
queue.add(i);
Thread.sleep(1);
}
// Finish the queue.
queue.add(End);
} catch (InterruptedException ex) {
// Just exit.
}
}
}
static class Consumer implements Runnable {
final BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
boolean ended = false;
while (!ended) {
try {
Integer i = queue.take();
ended = i == End;
System.out.println(i);
} catch (InterruptedException ex) {
ended = true;
}
}
}
}
public void test() throws InterruptedException {
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
Thread pt = new Thread(new Producer(queue));
Thread ct = new Thread(new Consumer(queue));
// Start it all going.
pt.start();
ct.start();
// Wait for it to finish.
pt.join();
ct.join();
}
}
Don't let yourself be confused by how much code this is - most of it is just wrapping. The core functionality is:
At start - create a BlockingQueue and share it between the two threads.
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
Thread pt = new Thread(new Producer(queue));
Thread ct = new Thread(new Consumer(queue));
When an event happens, post to the queue.
queue.add(i);
The event handler feeds off the queue.
while (!ended) {
try {
Integer i = queue.take();
Note that take here will block until an event is posted or an interrupt occurrs.
You can use
Thread.sleep(Long.MAX_VALUE); // more than the life of your computer
or
synchronized(this) {
wait();
}
or this wake on interrupt but doesn't throw an exception
LockSupport.park();
However a more elegant solution is likely to be to use an ExecutorService is designed to be a sleeping thread pool which wakes when you give it work to do.
ExecutorsService executor = Executors.newSingleThreadExecutor();
// when you want it to do something
executor.submit(this::process);
Note: you should consider how you want to handle exceptions. In the example in your question, an exception or error will kill the thread and it will stop running. In my example it won't kill the thread pool but the actual exception could be lost. For this reason I suggest you write it like this.
executor.submit(() -> {
try {
process();
} catch(Throwable t) {
LOGGER.warning(t);
}
});
Note: instead of just calling process and it having to figure out what you want to do you can write it like this.
doSomething(string, number, pojo);
That way you can see what data you expect the background thread to work on.
For comparison, here is the TwoThread example using the current thread as a producer and an Executor Service.
public class TwoThreadsJava5 {
public static void main(String args[]) throws InterruptedException {
System.out.println("TwoThreads:Test - Java 5.0 style");
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 1000; i++) {
final int finalI = i;
executor.submit(() -> {
try {
System.out.println(finalI);
} catch (Throwable t) {
t.printStackTrace();
}
});
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
}
}
And in Java 8 you could write
public class TwoThreadsJava8 {
public static void main(String args[]) throws InterruptedException {
System.out.println("TwoThreads:Test - Java 8 style");
IntStream.range(0, 1000)
.parallel()
.forEach(System.out::println);
}
}
I have 2 threads which I want to synchronize with wait() and notify(). However when I notify the thread which waits never resumes. This are my pieces of code.
In Lib60870 i start both threads, and thread HandShake is synchronized with SerialReader.
public Lib60870(){ //Here I start threads
try {
myConnection=new Connection(LOCALHOST,port);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mySerialReader.start();
myHandshake.start();}
}
Class SerialReader
public class SerialReader extends Thread {
private static boolean isPaused=true;
#Override
public void run() {
synchronized(this){
if(Lib60870.myConnection!=null){
while(true){
if(!isPaused){
byte inByte=Lib60870.myConnection.getByte();
if(inByte==0x68){
...
}
notify();
}
else if(inByte==0x10){
...
}
notify();
}
}
}
}
}
}
public void setPause(boolean pause){
isPaused=pause;
}
Class Handshake
public class HandShake extends Thread {
public void run() {
synchronized(Lib60870.mySerialReader){
Lib60870.mySerialReader.setPause(false);
...
try {
Lib60870.mySerialReader.wait();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Lib60870.mySerialReader.setPause(true);
...
Lib60870.mySerialReader.setPause(false);
try {
Lib60870.mySerialReader.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Thanks in advance
There are many problems with your approach:
Extending Thread is considered bad practice.
Using wait/notify for something that can be done with something in java.util.concurrent is not a good idea.
Falling into a tightly spinning loop is not pausing.
Here is a pauseable thread class. Write yourself a Stepper object and use one of these to execute the step() method continuously while not paused. Use its pause/resume methods to pause it cleanly.
/**
* PauseableThread is a Thread with pause/resume and cancel methods.
*
* The meat of the process must implement `step`.
*
* You can either extend this and implement `step` or use the factory.
*
* I cannot extend Thread because my resume will clash.
*
*/
public abstract class PauseableThread implements Runnable {
// The lock.
private final ReadWriteLock pause = new ReentrantReadWriteLock();
private final Lock readLock = pause.readLock();
private final Lock writeLock = pause.writeLock();
// Flag to cancel the whole process.
private volatile boolean cancelled = false;
// The exception that cause it to finish.
private Exception thrown = null;
// The thread that is me.
private Thread me = null;
#Override
// The core run mechanism.
public void run() {
// Track my current thread.
me = Thread.currentThread();
try {
while (!finished()) {
// Block here if we're paused.
blockIfPaused();
// Don't do any more work if we've been asked to stop.
if (!finished()) {
// Do my work.
step();
}
}
} catch (Exception ex) {
// Just fall out when exception is thrown.
thrown = ex;
}
}
// Have we finished yet?
private boolean finished() {
return cancelled || me.isInterrupted();
}
// Block if pause has been called without a matching resume.
private void blockIfPaused() throws InterruptedException {
try {
// Grab a write lock. Will block if a read lock has been taken - i.e. we've been paused.
writeLock.lockInterruptibly();
} finally {
// Release the lock immediately to avoid blocking when pause is called.
writeLock.unlock();
}
}
// Pause the work. NB: MUST be balanced by a resume.
public void pause() {
// We can wait for a lock here.
readLock.lock();
}
// Resume the work. NB: MUST be balanced by a pause.
public void resume() {
// Release the lock.
readLock.unlock();
}
// Stop.
public void cancel() {
// Stop everything.
cancelled = true;
}
// Stop immediately (if param is true).
public void cancel(boolean interrupt) {
if (interrupt) {
// Interrupt me.
me.interrupt();
} else {
// Or cancel me.
cancel();
}
}
// Wait for completion.
public void await() throws InterruptedException {
// Wait 'till we've finished. NB: Will wait forever if you haven't instigated a cancel of some kind.
while (me.isAlive()) {
Thread.sleep(0);
}
}
// Start - like a thread.
public void start() {
// Wrap me in a thread and fire the sucker up!
new Thread(this).start();
}
// Get the exception that was thrown to stop the thread or null if the thread was cancelled.
public Exception getThrown() {
return thrown;
}
// Expose my Thread.
public Thread getThread() {
return me;
}
// Create this method to do stuff.
// Calls to this method will stop when pause is called.
// Any thrown exception stops the whole process.
public abstract void step() throws Exception;
// Factory to wrap a Stepper in a PauseableThread
public static PauseableThread make(Stepper stepper) {
StepperThread pauseableStepper = new StepperThread(stepper);
// That's the thread they can pause/resume.
return pauseableStepper;
}
// One of these must be used.
public interface Stepper {
// A Stepper has a step method.
// Any exception thrown causes the enclosing thread to stop.
public void step() throws Exception;
}
// Holder for a Stepper.
private static class StepperThread extends PauseableThread {
// The actual stepper I am proxying.
private final Stepper stepper;
StepperThread(Stepper stepper) {
this.stepper = stepper;
}
#Override
public void step() throws Exception {
stepper.step();
}
}
// !!!! Testing only below !!!!
// My test counter.
static int n = 0;
// Test/demo.
public static void main(String[] args) throws InterruptedException {
try {
// Simple stepper that just increments n.
Stepper s = () -> {
n += 1;
Thread.sleep(1);
};
PauseableThread pt = PauseableThread.make(s);
// Start it up.
pt.start();
Thread.sleep(1000);
pt.pause();
System.out.println("Paused: " + n);
Thread.sleep(1000);
System.out.println("Resuminng: " + n);
pt.resume();
Thread.sleep(1000);
pt.cancel();
pt.await();
System.out.println("Finished: " + n);
// Start again to test agressive cancelling.
n = 0;
pt = PauseableThread.make(s);
// Start it up.
pt.start();
Thread.sleep(1000);
pt.pause();
System.out.println("Paused: " + n);
Thread.sleep(1000);
System.out.println("Resuminng: " + n);
pt.resume();
Thread.sleep(1000);
// Cancel aggressively.
pt.cancel(true);
pt.await();
System.out.println("Finished: " + n);
System.out.println("thrown: " + pt.getThrown());
} catch (InterruptedException e) {
}
}
}
The main problem you have is that only one thread can hold a lock. This means while your notify() thread holds the lock, no other thread can be running in a block of code which holds that lock.
Move the synchronized block inside the if (isPaused) block so another thread can run in between.
Another problem you have is that your isPaused boolean is not volatile so it can be inlined, i.e. it might never stop. It shouldn't be static even if you know you will never have more than one of these, it's bad practice to use a static field for an instance variable.
When paused you should cause the CPU to sleep.
Whenever you notify() or notifyAll() this should cause a state changes your wait() should always check for that state change.
I am writing a barbershop program using threads. Currently I have one barber and multiple customers coming in at the same time. However, after the first run through the program, the rest of the customers get all messed up. They all sit down at the same time. Is there something that I missed? My code is:
public synchronized void enter(Customer cust) {
custList.add(cust);
getCut(cust);
}
public synchronized void getCut(Customer cust) {
try {
notify();
wait();
System.out.println("sit down");
notify();
if (cashier==0) {
cashier++;
wait();
System.out.println("waiting to pay");
notify();
wait();
System.out.println("left the room");
chairs++;
cust.terminate();
}
} catch (InterruptedException ie) {}
}
This is my barber part of it:
public synchronized void cut(Barber barb) {
cashier=0;
try {
if(temp){
System.out.println(temp);
temp = false;
notify();
wait(); //wait for the customer to be settled in
System.out.println("go to cus");
notify();
wait();
System.out.println("cut cus hair");
notify();
wait();
if (cashier==1) {
System.out.println("got money");
notify();
cashier--;
barbers++;
}
}
} catch (InterruptedException ie) {}
}
}
public synchronized void goCut(Barber barb) {
cashier=0;
try {
if(temp){
System.out.println(temp);
temp = false;
notify();
wait();
System.out.println("walks to cus");
notify();
wait();
System.out.println("cut hair");
notify()
wait();
if (cashier==1) {
System.out.println("got the money");
notify();
cashier--;
barbers++;
}
}
From the oracle site
Note: Always invoke wait inside a loop that tests for the condition being waited for. Don't assume that the interrupt was for the particular condition you were waiting for, or that the condition is still true.
Please refer to Guarded blocks multithreading
It looks like you are using notify and wait randomly.
You have
notify();
wait();
at the beginning of the getCut method, what it does is:
the first client comes in, it calls notify, and then waits
the second client comes in, it calls notify - and thus it wakes the first client, and then it waits
the third client comes in, it calls notify - in result the second client wakes up and so on
Instead you should thing of using notify and wake to block a particular resource (chair).
private final Object pChairLock = new Object();
private int pAvaliableChairs = 3;
...
// take the resource
synchronized(pChairLock)
{
// wait until a chair is avaliable
while(pAvaliableChairs == 0)
{
pChairLock.wait();
}
// take sit
pAvaliableChairs--;
}
// now the current thread 'is sitting'
// - it can do some work using the resource
// after finishing, release the resource
synchronized(pChairLock)
{
pAvaliableChairs--;
// notify all waiting thread that resource is available
pChairLock.notifyAll();
}
In this case you could just use notify(), but if different threads are waiting to release resource and to take it, then calling notify could wake a wrong thread.
Don't worry about waking too much thread at the same time, as each thread will check if the resource is available and only the first one will be able to take it - the rest will resume waiting.
This example uses three chairs, but you can use just one (boolean) or any other number.
You can do the same with cashiers.
Use the code below as a template (from Magee & Kramer's textbook)...
ProducerConsumer = BarberShop
create BarberShop with size of 1
get = giveCut (barber "gets" a customer and gives customer a haircut)
put = getCut (customer requests a haircut - i.e. "puts" a customer request for a haircut)
code:
public class ProducerConsumer {
protected Object[] buf;
protected int count = 0;
protected int size;
public ProducerConsumer(int size) {
this.size = size;
buf = new Object[size];
}
public synchronized void put(Object o) throws InterruptedException {
while (count == size) wait();
buf[count] = o;
++count;
notifyAll();
}
public synchronized Object get() throws InterruptedException {
while (count == 0) wait();
--count;
Object o = buf[count];
buf[count] = null;
notifyAll();
return (o);
}
}
public class thread extends Thread {
static volatile boolean done = false;// volatile keyword is used
#Override
public void run() {
while (!done) {
for (int i = 1; i < 10; i++) {
try {
thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(currentThread());
System.out.println("1st thread>> " + i);
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread th = new Thread(new thread(),"mythread");
th.start();
for (int i = 1; i < 10; i++) {
thread.sleep(400);
System.out.println(currentThread());
System.out.println("2nd thread>> " + i);
if (i == 4) {
done = true;// safe way to stop a thread
break;
}
}
}
}
I am using volatile static variable here.Is it a safe way to stop a thread and also
when I print currentThread() method I get the output like Thread[mythread,5,main]
what does the 5 and main refer to??
It's a safe way to stop a thread, but there is no reason for the variable to be static: you want to stop one thread, not all threads of the same class.
Moreover, there is a more standard and less fragile way to stop a thread: interrupting it.
public void run() {
while (!Thread.currentThread().isInterrupted() {
...
}
}
...
th.interrupt();
This has the additional advantage that a thread which is sleeping or waiting, or blocked in an interruptible IO method will be woken up with an InterruptedException. When such an exception happens, it means that the thread should stop running, so you shouldn't swallow the exception as you did. Instead, you should return from the run method as fast as possible:
try {
thread.sleep(200);
}
catch (InterruptedException e) {
return;
}
Thread to toString, which is what is being called when you do System.out.println(currentThread()) prints out the thread name, priority, and thread group.
I'm assuming you are trying to interrupt the thread for something other then a normal completion, so why not just use Thread.interrupt() and Thread.isInterrupted()?