This is a strange situation I've run into. I have an abstract base class that defines a protected field. There is also a public method that modifies the field. I then have some subclasses of the base class that make use of the field.
I've noticed that when I invoke the super-class method to modify the field, the change to the field's value does not seem to "carry through" to an instance of a subclass.
The other thing that needs to be mentioned is that the abstract class (and therefore its subclasses) implements Runnable. I wouldn't think that should have an effect on what I'm seeing, but multi-threading is not my forte.
Abstract base class:
public abstract class AbstractWidget implements Runnable {
// Other fields and methods omitted for brevity.
protected boolean running;
public void shutDown() {
running = false;
}
}
Subclass:
public class ConcreteWidget extends AbstractWidget {
// Other fields and methods omitted for brevity.
#Override
public void run() {
running = true;
while (running) {
// ...
}
logger.info("Shutting down");
}
}
So, when I finally invoke the shutDown() method, the subclass instance, running in a thread does not break from it's loop and return.
I've used the technique of modifying a boolean field from "the outside" to stop a "forever" thread many times before. I don't understand what's happening here.
UPDATE:
Below is an example of the code being called.
ConcreteWidget widet = new ConcreteWidget(...);
thread = new Thread(widget);
thread.start();
logger.info("Started");
...
logger.debug("shutting down");
widget.shutDown();
try {
logger.debug("doing join on thread");
thread.join();
logger.debug("returned from join");
} catch (InterruptedException e) {
logger.error("Exception", e);
}
The call to join() never returns.
UPDATE:
As requested I have included what I hope is a complete (enough) example of the code as I currently have it. NOTE: I have taken the suggestion and changed the protected boolean to AtomicBoolean.
public abstract class AbstractWidget implements Runnable {
protected final AtomicBoolean running = new AtomicBoolean(true);
public void shutDown() {
running.set(false);
}
}
public class ConcreteWidget extends AbstractWidget {
#Override
public void run() {
while (running.get()) {
// ... do stuff (including calling process() below)
}
}
private void process() {
try {
// ... do stuff
} catch (IOException e) {
logger.error("Exception", e);
running.set(false);
return;
}
}
}
In the "main" logic:
private void startService() {
widget = new ConcreteWidget(...);
thread = new Thread(widget);
thread.start();
logger.info("Started");
}
public void close() {
logger.debug("shutting down service");
widget.shutDown();
try {
logger.debug("doing join on service thread");
thread.join();
logger.debug("returned from join");
} catch (InterruptedException e) {
logger.error("Exception", e);
}
}
BTW, it still does not work.
Your problem is actually a simple one. By the time you call widget.shutDown();, the thread has not actually started, so when the thread actually starts, it sets running back to true, and never stops. Instead of using running to terminate the loop, use a separate stopped variable.
public abstract class AbstractWidget implements Runnable {
// Other fields and methods omitted for brevity.
private volatile boolean running = false;
private valatile boolean stopped = false;
public boolean isRunning() {
return running;
}
public boolean hasStopped() {
return stopped;
}
public void shutDown() {
stopped = true;
}
}
public class ConcreteWidget extends AbstractWidget {
// Other fields and methods omitted for brevity.
#Override
public void run() {
running = true;
while (!stopped) {
// ...
}
running = false;
logger.info("Shutting down");
}
}
With this setup, you might want to wait a while before stopping, if not the loop will never run at all.
ConcreteWidget widet = new ConcreteWidget(...);
thread = new Thread(widget);
thread.start();
logger.info("Started");
...
try {
Thread.sleep(500); // <--
} catch (Exception e) {}
logger.debug("shutting down");
widget.shutDown();
try {
logger.debug("doing join on thread");
thread.join();
logger.debug("returned from join");
} catch (InterruptedException e) {
logger.error("Exception", e);
}
Do you run widget.shutDown(); immediately after thread.start(); ?
maybe widget.shutDown(); has run before running = true; code inside run() method
[facepalm]
It turns out the problem was that the thread processing was hanging and never able to check the state of the running field. Once I corrected that problem, it worked just fine.
I did change my logic to use the AtomicBoolean instead of boolean, so thank you for that useful advice.
Related
I'm looking to use a thread to process something in the background. Since this code isn't used anywhere else & is not complex I'd like to use an inline function. However the function needs a copy of an attribute at the time the thread was created i.e.: I'd like it if the output from the following example 'true' instead of 'false'
public class InlineThreadTest {
boolean value;
public static void main(String[] args) {
new InlineThreadTest();
}
InlineThreadTest() {
value = true;
java.util.concurrent.Executors.newSingleThreadExecutor().execute(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
System.out.println(value);
}
});
value = false;
}
}
... I can do what I'm looking to do by creating a separate class that implements Runnable, but having this inline seems like something that might be good.
I had a look # https://stackoverflow.com/a/362443/64696 , but cannot figure out how to mold this to my use case.
Runnable implementation is a thread and thread won't return any value. The ExecutorService.execute method just runs the thread and you have no way to get the state of the thread whether it was executed or not.
If you want to check for the task (not thread) executed by ExecutorService you should use Callable and work with sumbit(). Your modified example:
public class InlineThreadTest {
boolean value;
public static void main(String[] args) {
new InlineThreadTest();
}
InlineThreadTest() {
value = true;
java.util.concurrent.Future<Boolean> f =
java.util.concurrent.Executors.newSingleThreadExecutor().submit(new Callable<Boolean>() {
public Boolean call() {
System.out.println(value);
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
value = false;
return value;
}
});
try {
System.out.println(f.get()+" or value="+value);
} catch (Exception ex) { }
}
}
You'll get 2 lines
true
false or value=false
The Oracle Java SE Docs recommend doing this:
You can avoid the use of Thread.stop by replacing the applet's stop and run methods with:
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
Is there a way to do the same thing for a class blinker implements Runnable ?
As you would have to use blinker thisClass = this; or similar, wouldn't the (blinker == thisClass) always evaluate as true?
Or will this code suffice:
class blinker implements Runnable {
boolean stop = false;
#override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// code
// ...
if (stop) { Thread.currentThread().interrupt(); }
// ...
}
}
}
You could do something like that:
class Blinker implements Runnable {
Runnable blinker = this;
public void stop() {
blinker = null;
}
public void run() {
while(blinker == this) {
}
}
}
But it would be pretty pointless. I don't think you're understanding the point the documentation is trying to get across, which is don't use an infinite loop to keep threads alive, using Thread#stop() to terminate them. Instead, use a condition, then set it to false when you want to end the loop which is keeping the thread alive.
You do not need to constantly check Thread#isInterrupted() to keep the thread alive.
while(!stop) {
}
Would do just fine. You also should not interrupt the thread from within the thread. The purpose of interrupting is to end tasks that halt the thread. These tasks are surround within try/catch which catches an InterruptedException. Other threads are usually the ones in charge of interrupting.
The documentation is referring to allowing the thread to die gracefully.
In the first example, the run() method was handled via an infinite loop: while(true). The only way to stop the thread would be to forcing some kind of stop, such as usong Thread#stop:
public void run() {
while (true) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
But it's not recommended to use Thread#stop. Instead, the loop should depend on a boolean, which another thread (or the current one) could set to true or false:
private volatile boolean running;
public void stop() {
running = false;
}
public void run() {
while (running) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
Instead of using a running boolean, they used blinker == thisThread, then changed the value of blinker when they wanted to end the loop:
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
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
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
public class Common {
public synchronized void synchronizedMethod1() {
System.out.println("synchronizedMethod1 called");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronizedMethod1 done");
}
public void method1() {
System.out.println("Method 1 called");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method 1 done");
}
}
public class MyThread extends Thread {
private int id = 0;
private Common common;
public MyThread(String name, int no, Common object) {
super(name);
common = object;
id = no;
}
public void run() {
System.out.println("Running Thread" + this.getName());
try {
if (id == 0) {
common.synchronizedMethod1();
} else {
common.method1();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Common c = new Common();
MyThread t1 = new MyThread("MyThread-1", 0, c);
MyThread t2 = new MyThread("MyThread-2", 1, c);
t1.start();
t2.start();
}
}
Output:
Running ThreadMyThread-1
synchronizedMethod1 called
Running ThreadMyThread-2
Method 1 called
synchronizedMethod1 done
Method 1 done
I would like to find a way to prevent method1() from running when i called synchronizedMethod1. Unless I'm mistaken all methods are called and Java compiles them during and before runtime regardless if it's synchronized or not.
Should i have used a Lock object instead and/or not also make method1() a synchronized method?
I would like to find a way to prevent method1() from running when i called synchronizedMethod1
The easiest way to do this is to make method1() also be synchronized. This will mean that both methods will cause a lock on the instance of Common that they are calling. Only one thread will be able to either be calling synchronizedMethod1() or method1().
Unless I'm mistaken all methods are called and Java compiles them during and before runtime regardless if it's synchronized or not.
I don't understand this question. You really should not have to worry about the compilation or optimization phase of the JVM.
Should i have used a Lock object instead?
Usually making a method synchronized is considered not as good as using a private final lock object. Lock objects just allow you to be more fine grained in your locks. For example, with method locking, log messages and other statements that do not need protection will be synchronized as well. But if the goal is to lock the entire method then synchronizing the methods is fine.
If you want method1 and synchronizedMethod1 to be mutually exclusive then you need to guard them with the same lock. Whether this is using a Lock or simply calling synchronize on the same Object instance, the outcome is roughly the same.
On the off chance you want multiple threads to be allowed to execute method1 but not when synchronizedMethod1 is being invoked, you need a ReadWriteLock to accomplish that.
public class Common {
ReadWriteLock rwLock = new ReentrantReadWriteLock();
public void synchronizedMethod1() {
rwLock.writeLock().lock();
try {
System.out.println("synchronizedMethod1 called");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronizedMethod1 done");
} finally {
rwLock.writeLock().unlock();
}
}
public void method1() {
rwLock.readLock().lock();
try {
System.out.println("Method 1 called");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method 1 done");
} finally {
rwLock.readLock().unlock();
}
}
}