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();
}
}
Related
I know that there are a lot of similar questions, but no one helped me. I am getting IllegalMonitorStateException: object not locked by thread before wait() when I try to pause the thread.
Here is my initialization method:
// called only once in constructor; the variables are global ( private Thread ... )
public void init() {
recordingThread = new Thread(new Runnable() {
#Override
public void run() {
isNewRecordingThread= false;
record();
}
});
recognitionThread = new Thread(new Runnable() {
#Override
public void run() {
isNewRecognition= false;
recognize();
}
});
...
}
startRecording method:
private synchronized void startRecording(Thread recordingThread) {
if(isNewRecordingThread){
recordingThread.start();
return;
}
recordingThread.notify();
}
startRecognition method:
private synchronized void startRecognition(Thread recognitionThread) {
shouldContinueRecognition = true;
if(isNewRecognition){
recognitionThread.start();
return;
}
recognitionThread.notify();
}
And the stopping method where I actually get the error:
private synchronized void stopRecordingAndRecognition(Thread recordingThread, Thread recognitionThread) {
try{
if (recordingThread != null && recordingThread.isAlive()) {
recordingThread.wait();
}
if (recognitionThread != null && recognitionThread.isAlive()) {
recognitionThread.wait();
}
} catch (InterruptedException e){
Log.d("TESTING","InterruptedException e= "+e);
}
}
"object not locked by thread before wait()"
Think, what object is meant in this message? That very object for which wait() is applied:
recordingThread.wait();
that is, recordingThread.
synchronized void stopRecordingAndRecognition is irrelevant because it locks this object, and not recordingThread.
So, there are 2 solutions:
force methods to synchronize on recordingThread
embed synchronized methods into the class of recordingThread
"The goal is to start thread, pause it and after resume"
Pausing and resuming threads in Java is a bad practice because leads to subtle and hard to debug errors.
The only reliable way to stop/resume some computational process is to split this process into parts, process that parts in a loop, and before the start of processing the next part, checking if processing is allowed.
As an evolution of this approach, each part is formed as a Runnable and is submitted to a single-threaded Executor. Instead of stop and resume the Executor, producer thread(s) simply stop and resume submitting the partial tasks to the executor.
If (some) parts can be processed in parallel, then multithreaded executor can be used, but it requires coordination between submitting particular tasks.
The goal is to start thread, pause it and after resume
Here is a code snippet that I use for suspending and resuming a thread.
public class ThreadStatus {
private boolean paused;
private final String threadName;
private final ReentrantLock lock;
private final Condition condition;
public ThreadStatus (String name) {
threadName = name;
lock = new ReentrantLock();
condition = lock.newCondition();
paused = false;
}
// check for the thread to be paused
public void checkForPause() {
lock.lock();
try {
while (paused) {
condition.await();
}
} catch (InterruptedException ie) {
// interrupted
} finally {
lock.unlock();
}
}
// Pause the thread
public void pause() {
lock.lock();
try {
paused = true;
} finally {
lock.unlock();
}
}
// Resume the thread
public void resume() {
lock.lock();
try {
paused = false;
condition.signalAll();
} finally {
lock.unlock();
}
}
#Override
public String toString() {
return threadName;
}
}
If you need you could implement isStopped() or isRunning() similarly.
final ThreadStatus threadStatus = new ThreadStatus("Thread-A");
In the client code, call threadStatus.checkForPause() at the relevant point. For example, if you have some repeated processings inside a loop, you can do something like -
while (!threadStatus.isStopped()) {
threadStatus.checkForPause();
// do your processing here
}
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 :)
I want to pause and start thread untill variable standby.
But wait() and notify() is not work for me.
Is this a collect way to pause thread?
private boolean _threadIsWaiting = true;
private Object _specialObjectFromHttp;
public void methodToUse() {
Thread thread = new Thread(new Runnable() {
getParamsFromHttp();
while (_threadIsWaiting) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
convertObject(_specialObjectFromHttp);
)};
}
// Callback method (Thread wait for this.)
private void getParamsFromHttpCallBack(Object result) {
_specialObjectFromHttp = result;
_threadIsWaiting = false;
}
You could use an object to wait on, and call notify on it. I believe that to be the better approach (Actually, it is almost always better to utilize such a mechanism instead of sleeping and bool checking).
private Object _specialObjectFromHttp;
public void methodToUse() {
Thread thread = new Thread(new Runnable() {
getParamsFromHttp();
_specialObjectFromHttp.wait();
)};
}
// Callback method (Thread wait for this.)
private void getParamsFromHttpCallBack(Object result) {
_specialObjectFromHttp = result;
_specialObjectFromHttp.notifyAll();
}
In this case it seems plausible to just use the object that is being used in that control flow anyways, but you could also just add another object that has no purpose other than being waited for.
You could use a SynchronousQueue this will block until the information you need is provided. So in one thread call take, this will wait for a put on a different thread.
Both methods are blocking and no manual syncing is needed.
I want to know the best way how to notify another thread. For example, I have a background thread:
public void StartBackgroundThread(){
new Thread(new Runnable() {
#Override
public void run() {
//Do something big...
//THEN HOW TO NOTIFY MAIN THREAD?
}
}).start();
}
When it finished it has to notify main thread? If somebody knows the best way how to do this I'll appreciate it!
The typical answer is a BlockingQueue. Both BackgroundThread (often called the Producer) and MainThread (often called the Consumer) share a single instance of the queue (perhaps they get it when they are instantiated). BackgroundThread calls queue.put(message) each time it has a new message and MainThread calls 'queue.take()which will block until there's a message to receive. You can get fancy with timeouts and peeking but typically people want aBlockingQueueinstance such asArrayBlockingQueue`.
Purely based on your question you could do this:
public class test
{
Object syncObj = new Object();
public static void main(String args[])
{
new test();
}
public test()
{
startBackgroundThread();
System.out.println("Main thread waiting...");
try
{
synchronized(syncObj)
{
syncObj.wait();
}
}
catch(InterruptedException ie) { }
System.out.println("Main thread exiting...");
}
public void startBackgroundThread()
{
(new Thread(new Runnable()
{
#Override
public void run()
{
//Do something big...
System.out.println("Background Thread doing something big...");
//THEN HOW TO NOTIFY MAIN THREAD?
synchronized(syncObj)
{
System.out.println("Background Thread notifing...");
syncObj.notify();
}
System.out.println("Background Thread exiting...");
}
})).start();
}
}
and see this output
PS C:\Users\java> javac test.java
PS C:\Users\java> java test
Main thread waiting...
Background Thread doing something big...
Background Thread notifing...
Background Thread exiting...
Main thread exiting...
Just call notify()
public void run() {
try {
while ( true ) {
putMessage();
sleep( 1000 );
}
}
catch( InterruptedException e ) { }
}
private synchronized void putMessage() throws InterruptedException {
while ( messages.size() == MAXQUEUE )
wait();
messages.addElement( new java.util.Date().toString() );
notify();
}
You can't "notify the main thread".
The best approach is to use an ExecutorService, like this for example:
import java.util.concurrent.*;
// in main thread
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<?> future = executorService.submit(new Runnable() {
#Override
public void run() {
//Do something big...
}
});
future.get(); // blocks until the Runnable finishes
The classes are written specially to deal with asynchronous operations, and all the code in there is already written for you and bullet-proof.
Edit
If you don't want to block the main thread while waiting, wait within another thread:
final Future<?> future = executorService.submit(new Runnable() {
#Override
public void run() {
//Do something big...
}
});
new Thread(new Runnable() {
#Override
public void run() {
future.get(); // blocks until the other Runnable finishes
// Do something after the other runnable completes
}
}).start();
One thread notifying another thread is not a good way to do it. Its better to have 1 master thread that gives the slave thread work. The slave thread is always running and waits until it receives work. I recommend that you draw two columns and determine exactly where each thread needs to wait.
public void run()
{
//Do something big...
synchronized(this)
{
done = true;
}
}
Java includes libraries that make this really easy see ExecutorService and the following post
Producer/Consumer threads using a Queue
Is it possible to call wait method for another thread rather than the current thread.what I am asking is something like this :
Code:
public class a extends JApplet{
JButton start= new JButton("Start");
JButton wait= new JButton("Wait");
JButton notify = new JButton("Notify");
final Thread bthread = new Thread(new B(), "BThread");
#Override
public void init(){
//start
this.getContentPane().setLayout(new FlowLayout());
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Started");
}
});
this.getContentPane().add(start);
//wait
wait.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Waited");
synchronized(bthread) //something like this
{
try {
bthread.wait(); //is it possible instead of the current thread the bthread get invoke
} catch (Exception ex) {
Logger.getLogger(a.class.getName()).log(Level.SEVERE, null, ex);
}}
}
});
this.getContentPane().add(wait);
//notify
notify.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Notified");
synchronized(a.this){
a.this.notify();
}}
});
this.getContentPane().add(notify);
}
class B implements Runnable
{
int i=0;
#Override
public void run() {
while(i<10){
System.out.println(" i = "+i);
// i++;
}
}
}
}
Is it possible that when wait button is clicked the bthread go into wait state?
do you want bthread to actually pause its execution, whatever it is doing? There's no way to do that, AFAIK. You may however set bthread polling on some shared stateful synchronization object (a CountDownLatch or a Semaphore for instance, look into the java.util.concurrent package), so that you alter the status of the object to set bthread waiting.
No. You can't suspend a thread like that.
But you can implement a wait method in the B class:
class B implements Runnable
{
private boolean wait = false;
public void pause() {
wait = true;
}
int i=0;
#Override
public void run() {
while(i<10){
if (wait) {
wait();
}
System.out.println(" i = "+i);
// i++;
}
}
}
I dont think so.
Thread B can check some variable, for example boolean pause; If its true it can wait. It needs to be volatile or needs synchronization and something to wake it up is needed, but that depends on what you want it to do.
But if thread B is doing some long operation, it can be running long time before it checks whether it should wait.
No, you can only control the current thread, if you wait on another thread you actually call wait() using that object (the thread you are referring to) as a monitor. So you either have to time out, or someone call interrupt on that object to make your current thread start again.
You have to build that logic into your program, causing it to wait after a variable or message be flagged. Another way would be using locks or semaphores.
You could also call interrupt on that thread if you want it to stop, but that logic must also be built into your program, as it might just throw an InterruptedException if the thread is doing IO.