I started "play" with Threads in Java
and wondering about my solution with starting pausing and stopping thread...
Start and Pause works everytime (i think) fine, but when i do Stop method i get Exception:
java.lang.InterruptedException: sleep interrupted
but is stopped after that (i think so)
this is my super simple code :)
code snippet with buttons:
var ref = new Object() {
Thread th = new Thread(main);
};
startItem.addActionListener(e -> {
if (ref.th.getState() == Thread.State.NEW)
ref.th.start();
else
main.setPaused(false);
});
pauseItem.addActionListener(e -> {
if (ref.th.getState() == Thread.State.TIMED_WAITING)
main.setPaused(true);
});
stopItem.addActionListener(e -> {
main.setRunning(false);
ref.th.interrupt();
ref.th = new Thread(main);
});
and here my Runnable class:
public class MyRunnable implements Runnable {
private volatile boolean running;
private volatile boolean paused;
#Override
public void run() {
Logger.info("MONITORING STARTED");
running = true;
paused = false;
int counter = 0;
while (running) {
if (!paused) {
sleep();
System.out.println("thread working: " + counter);
counter++;
}
}
}
public void setRunning(boolean running) {
if(!running)
Logger.info("MONITORING STOPPED");
this.running = running;
}
public void setPaused(boolean paused) {
if(paused)
Logger.info("APPLICATION PAUSED = TRUE (paused)");
else
Logger.info("APPLICATION PAUSED = FALSE (continues to work...)");
this.paused = paused;
}
private void sleep() {
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Am I doing it correctly?
Or is this a stupid approach and should I do it differently to make it correct?
Whenever I "sweat out" some code, I wonder if I'm doing it in a nice and correct way... it's rather a sign of a lack of skills and professionalism :(
Thank you in advance for your help and patience and sorry for my english. :) Regards.
Your thread is printing the error message because you wrote ex.printStackTrace(). That's what printStackTrace() is for: You use it to call attention to an unexpected exception.
But if your other thread calls ref.th.interrupt(), then is the exception really unexpected? There's no rule that says you must call printStackTrace() every time your code handles an exception. It looks like you're already using Log4J, so one option would be to call Logger.info("interrupted", ex). Another option would be to simply do nothing at all in the handler, because after the handler is finished, the thread eventually* will check the running flag.
* Personally, I would move the sleep() call to the bottom of the loop because that way, if the sleep() is interrupted, it won't print "working" or increment the counter again until the thread is un-paused.
while (running) {
if (!paused) {
System.out.println("thread working: " + counter);
counter++;
sleep();
}
}
Better still: Move the sleep() out of the if statement, so that the thread will not consume 100% CPU time (as mentioned in a comment by #MadProgrammer) while it is "paused."
while (running) {
if (!paused) {
System.out.println("thread working: " + counter);
counter++;
}
sleep();
}
Related
I am starting a new thread in my app's onCreate() method like so:
stepsLogger = new Runnable() {
while(!Thread.currentThread().isInterrupted()){
//my code
try {
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
loggerThread = new Thread(stepsLogger);
loggerThread.start();
While it is not interrupted, it is supposed to do its thing every 10 seconds.
I am logging some text at the start of the Runnable to see how often the code gets run. The first time I run the app it's fine, but every time i restart, the text gets logged more frequently which means that more threads are running.
I have tried to stop them in the onDestroy() method:
#Override
protected void onDestroy() {
super.onDestroy();
loggerThread.interrupt();
loggerThread = null;
}
How do I make sure that the old thread gets stopped whenever the app is restarted?
Thread.interrupt() will wake up a sleeping thread with an InterruptedException, so you're most of the way there already. I'd change your loop in the following way:
while (true) {
// some code
try {
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // restore the thread's interrupted flag
break;
}
}
The bit about re-interrupting the thread is subtle. You can read more about it in this post from one of the primary JVM architects: https://www.ibm.com/developerworks/library/j-jtp05236/
In case this link ever dies, the gist of it is that there can be multiple "recipients" of thread interruption. Catching the exception implicitly clears the thread's interrupted flag, so it's useful to set it again.
You could use a volatile boolean variable to determine when to stop. Something like this:
class WorkerRunnable implements Runnable {
private volatile boolean shouldKeepRunning = true;
public void terminate() {
shouldKeepRunning = false;
}
#Override
public void run() {
while (shouldKeepRunning) {
// Do your stuff
}
}
}
To start it:
WorkerRunnable runnable = new WorkerRunnable();
new Thread(runnable).start();
To stop it:
runnable.terminate();
I have to check if an external service is up and running or is hung. If the external process is hung, I have to kill it and restart it.
PROBLEM STATEMENT:
To check if the process is hung, I try to invoke it. If it is hung, I wont get any response and I would know that the service is hung.
The problem is when I try to invoke the process, and if it is struck, even the java thread would be hung, So I thought I could create a thread and invoke the process in that thread.
I will have a counter in parent thread and if the child thread does not return in some time, I would kill (call inturrupt()) on it.
But even, the parent thread hangs here.
I have a Class MyThreadHandler as follows:
public class MyThreadHandler {
/**
* #param args
*/
public static void main(String[] args) {
MyThreadHandler myThreadHandler = new MyThreadHandler();
myThreadHandler.handleThread();
}
public void handleThread() {
System.out.println("STARTING LOOPER THREAD");
boolean isRunning = false;
int counter = 0;
MyThreaad myThread = new MyThreaad();
if (!isRunning) {
myThread.start();
System.out.println("aaaaaaaaaaaaaaaa");
isRunning = true;
}
while (true) {
System.out.println("while loop");
counter++;
if (!myThread.isAlive() || counter == 1000) {
System.out.println("HUNG THREAD::: Killing thread");
myThread.interrupt();
break;
}
}
}
}
My Thread class is as follows:
public class MyThreaad extends Thread{
public void run() {
System.out.println("STARTING LOOPER THREAD");
MyLooper myLooper = new MyLooper();
myLooper.loopIndefinite();
};
}
And MyLooper:
public class MyLooper {
public void loopIndefinite() {
while (true){
System.out.println("a");
}
}
}
I suspect the problem is that both loops stay busy. In this situation, the thread scheduler may execute one loop for a long time, and the other (parent) appears hung.
The MyLooper loop can not be changed, I guess, because it simulates the hung process. The following could be done to make sure the parent thread gets some execution time:
public void handleThread() {
System.out.println("STARTING LOOPER THREAD");
boolean isRunning = false;
int counter = 0;
MyThreaad myThread = new MyThreaad();
myThread.setPriority(Thread.MIN_PRIORITY); // <=== set priority
if (!isRunning) {
myThread.start();
System.out.println("aaaaaaaaaaaaaaaa");
isRunning = true;
}
while (true) {
try {
Thread.sleep(100); // <=== sleep
} catch(InterruptedException e) {
}
System.out.println("while loop");
counter++;
if (!myThread.isAlive() || counter == 1000) {
System.out.println("HUNG THREAD::: Killing thread");
myThread.interrupt();
break;
}
}
}
I added 2 lines, one to set the thread priority of the "hanging thread" to a low value, such that the parent thread gets execution time even when the thread is busy. The second line is a sleep, this makes sure the parent thread doesn't take all the available execution time.
If you don't check for the interrupted state there's no chance that myThread.interrupt() will do what you want.
you have to add the following in the loopIndefinite method:
if(Thread.interrupted()) throw new InterruptedException();
Your loops are very aggressive for the CPU, you should not stress CPU like that. It's better to use ExecutorServices and Future as suggested by Fildor.
When I tried to figure out how to stop a thread in a program with multiple threads,
I was suggested to call a method which actually sets a flag to tell that thread stop doing real works,like this:
public class ThreadTobeTerminated implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private volatile boolean running = true;
public void terminate() {
running = false;
}
#Override
public void run() {
while (running) {
try {
LOGGER.debug("Doing some real work ,like Counting...");
for(int i=0;i<100;i++){}
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
running = false;
}
}
}
}
when I want to stop this tread ,I'll call threadInstance.terminate();.
Don't I need to literally stop this thread ?
Why I should leave this thread to do some useless work (method run called ,test the flag running==false then return)? I mean :this is a waste of time ,isn't it?
When the execution scope goes beyond the run() method, the thread stops, so the moment that the while loop is broken, the thread will stop.
This would also allow you to do some clean up if the situation requires it:
public void run() {
while (running) {
try {
LOGGER.debug("Doing some real work ,like Counting...");
for(int i=0;i<100;i++){}
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
running = false;
}
}
//Clean up
}
The above approach allows you some control over how is the thread stops and what happens after as opposed to potentially just kill it, which could cause all kinds of problems.
I want to have a class that starts a Thread and provides methods to pause and continue this Thread. My first approach was to have flag, which loops a sleep method as long as the value is true. Something like :
public class Bot {
private Thread t ;
private boolean isPaused;
public Bot(){
t = new Thread(new Runnable(){
#Override
public void run() {
while (true) {
System.out.println("Hi");
while(isPaused){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
t.start();
}
public void pauseBot(){
isPaused = true;
}
public void continueBot(){
isPaused = false;
}
}
But since the Thread is still running and wasting CPU, I dont find this to be a good solution. How would this look with wait() and notify().
I had a look at various tutorials about that topic but somehow I couldnt apply them to my issue.
Everytime I tried it I either got IllegalMonitorStateException or the code stopped my whole application and not just the Thread I wanted to be stopped.
Another question I have is: How do prevent the Thread from beeing paused at a critical moment e.g.
Runnable r = new Runnable(){
#Override
public void run() {
while(true){
task1();
task2();
//Thread mustn't be stopped from here....
task3();
task4();
task5();
task6();
task7();
//... to here
task8();
task9();
task10();
}
}
};
Because when task3() .... task7() deal with something that would expire while the Thread is paused there must be a way to let the Thread finish task7() until it pauses.
I hope you can help me with my issue.
Thanks in advance,
Flo
So given this is your Thread class:
public class MyThread extends Thread
{
First, you need an lock object. This object can be everything, and if you use an existing object this takes less memory. Also define a flag if the bot should be paused.
public Object lock = this;
public boolean pause = false;
Now, define a pause() and continue() method for the thread. This sets the pause flag.
public void pause ()
{
pause = true;
}
public void continue ()
{
pause = false;
Here you need to wake up the thread. Note the synchronized on the lock object so that you don't get an IllegalMonitorStateException.
synchronized (lock)
{
lock.notifyAll();
}
}
No, define a method that automatically pauses the thread when it should be paused. You might call this at every moment when the thread can be paused.
private void pauseThread ()
{
synchronized (lock)
{
if (pause)
lock.wait(); // Note that this can cause an InterruptedException
}
}
Now, you can define your thread in the run() method:
public void run ()
{
task1();
task2();
pauseThread();
task3();
task4();
task5();
task6();
task7();
pauseThread();
task8();
task9();
task10();
}
}
I have a class which processes something. I'm trying to run a number of instances of this class in parallel.
However, I'm not sure if in TaskManager.startAll(), when I call r.go(), whether this would cause r to start running in its own thread, or within the main thread?
The total execution time that I'm getting seems to be very high, and despite my attempts at optimizing, nothing seems to be having any effect. Also, if I run a profiler on my project in Netbeans, it shows all the threads as sleeping. So I'd like to know if I'm doing something wrong?
This is the structure of the class:
public class TaskRunner implements Runnable {
private boolean isRunning = false;
public void run() {
while(true) {
while (! running) {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
process();
}
}
public void go() {
isRunning = true;
}
public void stop() {
isRunning = false;
}
private void process() {
//Do some number crunching and processing here
}
}
Here's how these are being run / managed:
public class TaskManager {
private ArrayList<TaskRunner> runners = new ArrayList<>();
public TaskManager() {
for (int i = 0; i < 10; i++) {
TaskRunner r = new TaskRunner();
new Thread(r).start();
runners.add(r);
}
}
public void startAll() {
for (TaskRunner r : runners) {
r.go();
}
}
}
Indeed, you are not "doing it right." If you want to create a multi-threaded Java application, the place to start is with the java.util.concurrent package.
It appears from your code that you want to run ten tasks in parallel. I assume that after "number crunching and processing," you'll want to aggregate the results and do something with them in the main thread. For this, the invokeAll() method of ExecutorService works well.
First, implement Callable to do the work you show in your process() method.
final class YourTask implements Callable<YourResults> {
private final YourInput input;
YourTask(YourInput input) {
this.input = input;
}
#Override
public YourResults call()
throws Exception
{
/* Do some number crunching and processing here. */
return new YourResults(...);
}
}
Then create your tasks and run them. This would take the place of your main() method:
Collection<Callable<YourResults>> tasks = new List<>(inputs.size());
for (YourInput i : inputs)
tasks.add(new YourTask(i));
ExecutorService workers = Executors.newFixedThreadPool(10);
/* The next call blocks while the worker threads complete all tasks. */
List<Future<YourResult>> results = workers.invokeAll(tasks);
workers.shutdown();
for (Future<YourResult> f : results) {
YourResult r = f.get();
/* Do whatever it is you do with the results. */
...
}
However, I'm not sure if in TaskManager.startAll(), when I call r.go(), whether this would cause r to start running in its own thread, or within the main thread?
So my first comment is that you should make isRunning be volatile since it is being shared between threads. If the threads are not starting when it goes to true (or seem to be delayed in starting) then I suspect that's your problem. volatile provides memory synchronization between the threads so the thread that calls go() and makes a change to isRunning will be seen immediately by the thread waiting for the change.
Instead of spinning like this, I would use wait/notify:
// this synchronizes on the instance of `TaskRunner`
synchronized (this) {
// always do your wait in a while loop to protect against spurious wakeups
while (!isRunning && !Thread.currentThread().isInterrupted()) {
try {
// wait until the notify is called on this object
this.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
Then in the go() method you should do the following. stop() would be similar.
public void go() {
synchronized (this) {
isRunning = true;
this.notifyAll();
}
}
Notice that you should handle thread interrupts carefully. Test for isInterrupted() in the while running loop and re-interrupt a thread when InterruptedException is thrown is always a good pattern.
The total execution time that I'm getting seems to be very high, and despite my attempts at optimizing, nothing seems to be having any effect. Also, if I run a profiler on my project in Netbeans, it shows all the threads as sleeping.
So although the threads are mostly sleeping, they are still each looping 1000 times a second because of your Thread.sleep(1). If you increased the time sleeping (after making isRunning be volatile) they would loop less but the right mechanism is to use the wait/notify to signal the thread.
Awful solution, terrible. first I highly recommend you start reading some tutorial like [this]
Second, if threads should wait for a signal to go for some job, so why just don't you wait them!!!!!, something like this
import java.util.ArrayList;
public class TaskManager
{
//////////////////////
public volatile static Signal wait=new Signal();
//////////////////////
private ArrayList<TaskRunner> runners = new ArrayList<>();
public TaskManager()
{
for (int i = 0; i < 10; i++)
{
TaskRunner r = new TaskRunner();
new Thread(r).start();
runners.add(r);
}
try {
Thread.sleep(1000);
startAll();
Thread.sleep(1000);
pauseAll();
Thread.sleep(1000);
startAll();
Thread.sleep(1000);
haltAll();System.out.println("DONE!");
}catch(Exception ex){}
}
public void startAll()
{
synchronized(wait){
wait.setRun(true);;
wait.notifyAll();
}
}
public void pauseAll(){
wait.setRun(false);
}
public void haltAll(){
for(TaskRunner tx:runners){tx.halt();}
}
public static void main(String[] args) {
new TaskManager();
}
}
class TaskRunner implements Runnable
{
private Thread thisThread;
private volatile boolean run=true;
public void run()
{
thisThread=Thread.currentThread();
while(run){
if(!TaskManager.wait.isRun()){
synchronized(TaskManager.wait)
{
if(!TaskManager.wait.isRun()){
System.out.println("Wait!...");
try
{
TaskManager.wait.wait();
}
catch (Exception e)
{
e.printStackTrace();
break;
}
}
}}
process();
}
}
private double r=Math.random();
private void process(){System.out.println(r);try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}}
public void halt(){run=false;thisThread.interrupt();}
}
class Signal{
private boolean run=false;
public boolean isRun() {
return run;
}
public void setRun(boolean run) {
this.run = run;
}
}
in above sample, all runners works till the Signal run boolean is true, and simple TaskManager class set tit as false for every time it needs to pause the threads. and about the halt, it just set the shutdown(run) flag to false, and also interrupt the thread because of if thread is in wait state.
I hope I could prove your solution is like dream-on story, and also could explained enough about my solution.
have a good parallel application :)