In my Android App there is an activity that contains a runnable inner class.
From this activity a new Thread running the inner class is created/started.
This thread executes this loop:
while (run) {
...
}
The state of the boolean "run" should be changed from both threads.
Thats why I put it into the activity class like this:
private static volatile boolean run;
I would like to know if this is a correct way of controlling a thread.
Do both threads use the same variable in the memory?
As neither checking nor setting a boolean is an atomic operation for the cpu, is it possible, that one thread checks "run" while the other thread is changing its state?
A thread will stop itself if the task you placed in the inner Runnable class was completed. So, keeping the Runnable alive will make the thread alive too, i.e. using while loop. And volatile boolean controls the change of run variable easily.
Do both threads use the same variable in the memory?
Yes. You haven't shown us much code, but since the variable is static, you've shown us enough. A static variable only exists in one place. Any code that can see it anywhere in your program is seeing the same variable.
I would like to know if this is a correct way of controlling a thread.
It is a fine way of signalling a thread.
The only reason why you might want to do differently is if the thread is not able to check the run variable often enough. Especially, if the thread waits for anything.
In that case, you might want to look into thread.interrupt() Interrupting any thread while it is waiting for something (in most cases) will cause the method that was waiting to throw an InterruptedException. That affords your thread the opportunity to check whether or not it still should be running.
Related
I have the following piece of code:
public static void main(String[] args) {
...
while(condition.continueListening()) {
}
log.info("Finished");
}
The condition object creates its own thread that after one condition is met, make the method continueListening, to return false.
The thing is that, I want the main thread to not to finish until that method returns false, and the way I implemented it, it's by using this structure that it's quite "hard" for the CPU, do you know any other approach that could work better?
What is continueListening checking? If its just a random piece of state, you don't really have a good choice, best you can do is make your thread sleep for a little bit, say a half second in the while loop.
But if you can change continueListening, then you can have it block until an event happens and it should continue. Java has many options for this, some could be:
You could wait for the other thread to exit using Thread.join().
Wait for the thread to notify on some object that it has done something (similar idea to join but the thread can carry on and do something else). Object.wait(), Object.notify().
Use the Java "executor", this is similar to waiting for a thread to exit, but has built in means to transfer results and errors, and allows Java to use things like thread pools. See ExecutorService and Future.get()
Various other waitable event objects or queues. Such as doing something manually with Future and Promise, or BlockingQueue.
is there any kind of Runnable, Callable or Thread with capability of stopping it in any duration of time?
I wrote something like this
public class ThreadRunner {
private ExecutorService threadPoolExecutor;
ThreadRunner() {
threadPoolExecutor = Executors.newSingleThreadExecutor();
}
public void startThread(String endPoint, ProgressBar progressBar) {
Runnable task = () -> {
// some code which saves images from URL (1230 images) and updates progress bar
};
threadPoolExecutor.execute(task);
}
public void stopThread() {
threadPoolExecutor.shutdownNow();
}
}
Thread runs correctly, images are being saved, progress bar being updated, but when I want to stop thread (or maybe even pause process of saving if possible) by calling ThreadRunner class's method - nothing happens.
Am I doing something wrong - or most likely - what am I doing wrong?
is there any kind of Runnable, Callable or Thread with capability of stopping it in any duration of time?
You can implement such a thing yourself, but there is no generic support available for it, unless you count the long-deprecated Thread.stop() methods. Under no circumstances should you use those methods, but do read their API docs for a discussion of why they are deprecated and what you can do instead. You can find a longer-form version of the discussion in Java's technical notes.
The bottom line is that the computation you want to be able to stop needs to periodically check some shared variable or built-in condition to determine whether to do so. You arrange for that variable to be set when you want the thread to stop, and if you need to block until it does stop then you join() it. Under some circumstances, it can be helpful to interrupt() the thread to get it to check the variable (or being interrupted can itself serve as the termination condition). The user-facing end of this can be wrapped up in a method.
In any case, an ExecutorService cannot give you a handle on this. Requesting such a service to shut down will prevent it from dispatching any more tasks, but there is no safe, general-purpose mechanism by which it could force a premature shutdown of tasks that are already running.
Once started, a thread will run until Runnable.run() exits. Due to several issues you should never use Thread.stop() or Thread.interrupt().
Instead, you will have to implement your own logic for exit/pause. A few suggestions:
For stopping the thread, you can make a boolean variable shouldExit. In your thread, check this variable every now and then, and just do "return" or break the for/while loop when it becomes true. Setting this variable from another thread should now make the downloader exit. If necessary, you should surround access to this variable with synchronized block as to prevent any race conditions.
For pausing the thread, you can use a similar approach. When you set a certain variable to true (e.g. isPaused), make the thread react by going into an Object.sleep(). This way, it won't consume any CPU during sleep. You can then use Object.notify() from another thread to "kick" the sleeping thread out ouf sleep. You will need a synchronized block here, too.
I have a small program presenting the user with a GUI to select a file, the program then executes based on the files contents and presents the results accordingly.
This is the loop running in the main thread (the main() method):
do {
args = fg.getFile();
} while (!fg.started);
fg.started is a boolean variable set to true when the user has selected a file and presses the "start" button.
However, this does not work UNLESS I put a random task inside the loop:
do {
args = fg.getFile();
System.out.println("");
} while (!fg.started);
This works.
Can anyone explain to me why this is?
I'm aware of a solution involving the Thread class, with notify() and wait() etc, but now I'm just curious about this.
fg.started is a boolean variable set to true when the user has selected a file and presses the "start" button.
However, this does not work UNLESS I put a random task inside the loop:
That's because two threads are accessing the started field without memory synchronization. You don't show the definition of fg.started but I suspect that you need to make sure that it is volatile. You also might consider switching to an AtomicBoolean. Here's the Java tutorial about memory synchronization.
volatile boolean started;
The issue with multi-threaded applications is that parts of your program can run in different processors with their own local memory cache. Whenever threads modify or access shared fields there needs to be explicit synchronization to ensure that they aren't just looking at the local cached value of the field.
It is working when you add a System.out.println(...) because the PrintStream's methods are synchronized so you are adding indirect memory synchronization.
making getFile() synchronized fixed it, thanks. Care to explain why? :)
Because, like the System.out.println(...) you are adding indirect synchronization.
You should syncronize the access of fg otherwise this may happen:
Thread1 could possibly become active, access and therefor block fg, and then get paused.
Thread2 becomes active, can't access fg and get's deactivated immediately.
Thread1 is active again, finishes the task an may instantaniously reaccess fg, then pause.
Thread2 becomse active and ... damn! fg is locked again!
If you need help/instructions on concurrency/parallel execution, see Oracle - Syncronization for information.
May I include a synchronized block inside another one for synchronizing another object?
Example:
synchronized(myObjetc1){
// code
synchronized(myObjetc2){
// code
}
}
If so, still, is it a correct technique or is it too risky?
It will be fine if you synchronize in the same order everywhere else.
If some other thread were to execute the following code
synchronized(myObjetc2){
// code
synchronized(myObjetc1){
// code
}
}
you might get a deadlock.
Assuming the variables above are referencing the same objects, consider the following case. The first thread (your code) locks the monitor on myObjetc1. The thread scheduler switches thread context. The second thread (the above code) locks the monitor on myObjetc2. The thread scheduler switches thread context. The first thread attempts to lock the monitor on myObjetc2. It has to wait because the second thread has it. The thread scheduler switches context. The second thread attempts to lock the monitor on myObjetc1. It has to wait because the first thread has it. Boom! Deadlock.
Yes, you can do it.
Till the time you are following lock rules and doing so solves your requirement, its Fine.
However, many times something like this invites DeadLock problem, if done incorrectly.
I have a thread:
class Foo extends Thread
{
boolean active = true;
public void run()
{
while(active)
{
//do stuff
}
}
public void end()
{
active = false;
}
public void hibernate()
{
synchronized(this)
{
wait();
}
}
}
If another thread calls end(), will Foo immediately see that active is now false? Specifically, because active isn't volatile, I'm not sure that it will. I initially created end() as a clever way of avoiding volatile, but now I'm unsure that it will actually do what I intend.
Additionally, if another thread calls hibernate(), which thread will go to sleep? I'm intending Foo to sleep, so if this doesn't do what I intend, an alternative suggestion would be very welcome.
If another thread calls end(), will Foo immediately see that active is now false?
No it won't. Or at least, it won't see it all of the time.
If you want run to always see the new value immediately, there has to be a "comes after" relationship between the thread assigning to the variable and the thread reading it. This can be achieved:
by declaring active volatile,
by putting synchronized blocks around the statements that read and write the variable,
by making the variable an "atomic" type; e.g. AtomicBoolean, or
by using some other appropriate concurrency class; see the java.util.concurrent.* packages.
... a clever way of avoiding volatile ...
Declaring the variable to be volatile is one way of ensuring proper synchronization. It is a fact that proper synchronization imposes a performance overhead. However, proper synchronization is essential for your application to work reliably, and it is NOT "clever" to avoid it.
(Without proper synchronization, your program will probably still work most of the time, and it might even always work on some machines. However, occasionally it won't work, and the actual behavior is likely to depend on what machine you run the program on, what the machine load is, and other things.)
Additionally, if another thread calls hibernate(), which thread will go to sleep?
The thread that makes the call will go to sleep. And it won't wake up unless some other thread does a notify or notifyAll on the same Foo object.
If you simply want the application to go to sleep and wake up a bit later, use Thread.sleep. But beware that using sleep in the wrong way can make your application slow and unresponsive.
Your suspicion is correct: because active isn't volatile, there is no guarantee that run() will ever see the change made on another thread.
Generally speaking, “clever” ways of avoiding volatile are almost always a bad idea. In fact, even volatile is something you should prefer not to resort to. Most of the time it's safer to stick to locks, monitors, or higher-level synchronization mechanisms.
For your second question, the thread that will go to sleep is the one that called hibernate(). That thread will sleep until it is interrupted, it experiences a spurious wakeup, or some other thread calls notify()/notifyAll() on the Foo instance's monitor. It is usually a mistake to call Object#wait() without surrounding it with a loop that checks the condition being waited for.
You also seem to be confused about the idea of a Foo instance “going to sleep”. A Foo instance isn't a Thread (or even a Runnable), and doesn't create its own thread, so the idea of it going to sleep doesn't make a lot of sense. What you are probably trying to achieve is putting the thread calling Foo#run() to sleep.
Regarding your first question of avoiding volatile , you should try using Thread interruption to signal a running thread to stop.
Use interrupt() instance method from another thread to interrupt running thread.
Use isInterrupted() method in your running thread to check for interruption.
while(!this.isInterrupted()){
//do your work here.
}
Not sure why you want to extend Thread class. If you implements Runnable in that case you should use interrupted in your run method to check for interruption . Please read javadocs to know about some caveats of this method.