I have a simple Question:
I have a Thread named rlMF. I created it this way:
public Thread rlMF = new Thread(new Runnable() {
public void run() {
reloadMissingFiles();
stopTh();
}
public void stopTh() {
activityStopped = true;
}
});
Now i want to call the stopTh Function from outer Thread. Why can't i simply call rlMF.stopTh(); and what can i do else?
Example:
protected void onPause() {
Log.d("Info", "destroying...");
activityStopped = true;
rlMF.stopTh();
super.onPause();
}
Is not working...
Because the interface accessible is from Thread. In order to have you method accessible from out, you need to specify a type that exposes this method.
And if you take a look carefully the method is implemented in the instance of Runnable. Not even in Thread.
You could have something like this if you really need to access the Runnable object:
class MyRunnable implements Runnable {
public void run() {
...
}
public void fooBar() {
...
}
}
public void someMethod() {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
...
myRunnable.fooBar();
...
}
An example for Francisco approach, besides what you are trying to achieve. Maybe this can point you in the right direction
public class CustomRun implements Runnable {
public void run() {
reloadMissingFiles();
stopTh();
}
public void stopTh() {
activityStopped = true;
}
}
In your Code
// start thread with custom runner
CustomRun runner = new CustomRun();
new Thread(runner).start();
// call your stopTh method on CustomRun class
protected void onPause() {
Log.d("Info", "destroying...");
activityStopped = true;
runner.stopTh();
super.onPause();
}
Your goal is to interrupt the thread from onPause. There are several ways to do it, but essentially, you will need to include some interruptibility in reloadMissingFiles.
Option 1
You can use a boolean flag like you did - you need to declare it as volatile to make sure the changes are visible across threads:
private volatile boolean activityStopped = false;
public void reloadMissingFiles() {
while (!activityStopped) {
//load small chunks so that the activityStopped flag is checked regularly
}
}
public Thread rlMF = new Thread(new Runnable() {
public void run() {
reloadMissingFiles(); //will exit soon after activityStopped has been set to false
}
});
protected void onPause() {
//This will stop the thread fairly soon if the while loop in
//reloadMissingFiles is fast enough
activityStopped = true;
super.onPause();
}
Option 2 (better approach)
I don't know what you do in reloadMissingFiles, but I suppose it is some sort of I/O operations, which are generally interruptible. You can then have an interruption policy where you stop as soon as an InterruptedException is caught:
public void reloadMissingFiles() {
try {
//use I/O methods that can be interrupted
} catch (InterruptedException e) {
//cleanup specific stuff (for example undo the operation you started
//if you don't have time to complete it
//then let the finally block clean the mess
} finally {
//cleanup (close the files, database connection or whatever needs to be cleaned
}
}
public Thread rlMF = new Thread(new Runnable() {
public void run() {
reloadMissingFiles(); //will exit when interrupted
}
});
protected void onPause() {
runner.interrupt(); //sends an interruption signal to the I/O operations
super.onPause();
}
Note: you can also read this article for a more in depth version of it.
Related
AIM : To make a generic Thread class that is independent of the parent calling it, can be started/stopped/paused/resumed by the parent class calling it and perform user defined tasks (via runnable)
MY RESEARCH :
SO_1
SO_2
SO_3
SO_4
SO_5
SomeBlog
SomeBlog2
OracleBlog
Problem : from what i have understood:
Starting a background thread: threadObj.start() will execute statements of run() function of a class implementing Runnable Interface.
Stopping a background thread : threadObj.interrupt() will stop a thread from executing
Pausing a thread : threadObj.wait() will pause the thread,although, it requires additional synchronised lock mechanism
Resuming a thread :threadObj.notifyAll() will release resume the object, after handling the synchronised lock mechanism
Thus based on this, i wrote a generic Thread class that is supposed to run a user's set of tasks and play/pause/resume/stop via ui buttons, BUT ITS NOT WORKING:
Generic Thread.java
public class PausibleThread extends Thread {
public static final String TAG ="PausibleThread>>";
#Nullable
PausibleRunnable runnable ;
public PausibleThread(#Nullable Runnable target) {
super(target);
PausibleRunnable r = new PausibleRunnable(target);
runnable=r;
}
#Override
public synchronized void start() { super.start(); }
public synchronized void stopThread(){ this.interrupt(); }
public synchronized void pauseThread(){ runnable.pause(); }
public synchronized void resumeThread(){ runnable.resume(); }
PausibleRunnable.java:
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class PausibleRunnable implements Runnable {
private Object lockerObject;
private boolean isPaused;
private boolean isFinished;
public static final String TAG="PausibleRunnable";
#Nullable
Runnable usrAction = null;
public PausibleRunnable(#NonNull Runnable usrAction) {
lockerObject = new Object();
isPaused = false;isFinished = false;
this.usrAction = usrAction;
}
public void run() {
while (!isFinished) {
if(isPaused) {
runPauseLoop();
}
else {
runUserAction();
isFinished=true;
}
}
}
private void runPauseLoop() {
synchronized (lockerObject) {
while (isPaused) {
try { lockerObject.wait(); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
private void runUserAction() {
if(usrAction !=null){ usrAction.run(); }
else { Log.e(TAG, "run: userAction is NULL" ); }
}
public void pause() {
synchronized (lockerObject) { isPaused = true; }
}
public void resume() {
synchronized (lockerObject) {
isPaused = false;
lockerObject.notifyAll();
}
}
}
Ui creating a Pausible Thread and implementing various functions of it:
//full class implementation at : https://paste.ubuntu.com/p/cTpW5Wt3Fy/
int totalRunTime = 20 * 5;
Pausible thread bgThread;
private void initThread() {
Runnable r = () -> {
try {
while (totalRunTime > 0) {
Thread.sleep(500);
totalRunTime--;
updateUi();
}
}
catch (Exception e) { e.printStackTrace(); }
};
bgThread = new PausibleThread(r);
}
private void updateUi() {
String data = "TotalRunTime=" + totalRunTime;
runOnUiThread(() -> tvTerminal.setText(data));
}
#Override
public void onClick(View v) {
if (bgThread == null) {
makeShortToast("Can't perform action, bg thread is null");
return;
}
if (v.getId() == fabPause.getId()) {bgThread.pauseThread(); }
else if (v.getId() == fabResume.getId()) { bgThread.resumeThread(); }
else if (v.getId() == fabStop.getId()) { bgThread.stopThread(); }
else if (v.getId() == fabStart.getId()) { bgThread.start(); }
}
But this does not work. Why? I am taking a wild guess here, but i think the runnable is only running user's action to run a big sized loop and not repeatedly checking for play/pause. So what am i supposed to do?
ui sample image : https://i.imgur.com/kmj3Bwt.png
You asked: "But this doesn't work. Why?"
I answer:
Your solution does not work because you are always running in the loop inside runUserAction. You never break out of that loop to check if you are paused.
I'm afraid you'll have to remodel your solution to run usrAction in shorter loops, otherwise you will either lose state (assuming you interrupt that loop from outside), which will end up in undefined behavior, OR you will only break out of it when it's over, OR you'll pause your loop at states you don't really want to pause at [e.g. while making a network call -- after resumed you'll get a SocketTimeoutException].
I'd suggest you to go with the former approach as it's more elegant.
Edit:
Another possible solution: every iteration inside the usrAction check for PausableThread's state, i.e. see whether it's paused, stopped or whatever.
Try this:
PausableRunnable.java
public synchronized boolean canContinue() throws Exception {
synchronized (lockerObject) {
if (isPaused) {
lockerObject.wait();
}
if (isFinished) {
return false;
}
return true;
}
}
PausableThread.java
public boolean canContinue() throws Exception {
return runnable.canContinue();
}
and the Application.java
private void initThread() {
Runnable r = () -> {
try {
while (totalRunTime > 0) {
if (bgThread.canContinue()) { // <--- !!!!!!
Thread.sleep(200);
totalRunTime--;
updateUi();
}
}
}
catch (Exception e) { e.printStackTrace(); }
};
bgThread = new PausibleThread(r);
}
This way you can run your application Runnable and still obey PausableThread's states at the times the runnable can tollereate. I.e. before/after transaction or other piece of calculation that is not supposed to be interrupted.
Edit 2:
feel free to lose ´synchronized´ modifier on methods like pause or resume, since you are already operating inside synchronized blocks in them.
I have these two methods for creating and stopping a thread. However the thread still keeps running, even after the first method is called. (I'm creating an object of the class and calling them from another class).
private Thread thread;
public void stopAlarm() {
Log.i(LOG_TAG, "stopAlarm called");
sendAlarm = false;
if (!thread.equals(null)) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void triggerAlarm() {
Runnable alarmTest = new Runnable() {
#Override
public void run() {
while (sendAlarm) {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
}
}
};
thread = new Thread(Test);
thread.start();
}
When stopAlarm is called the thread is always null, although it is called after triggerAlarm is called (thread is running).
Your problem is caused by thread scope. Thread scope is created when you create a thread with same variables in the scope but you can't change these variables from outside world. Best practice for managing runnables in android is to use Handler.
Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
#Override
public void run() {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
handler.post(alarmTest, 5000); //wait 5 sec and run again
//you can stop from outside
}
};
after definitions, in order to start the runnable:
handler.post(alarmTest,0); //wait 0 ms and run
in order to stop the runnable:
handler.removeCallbacks(alarmTest);
EDIT: wait statement with loop
EDIT: Complete solution
Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
#Override
public void run() {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
handler.post(alarmTest, 5000); //wait 5 sec and run again
//you can stop from outside
}
};
public void stopAlarm() {
Log.i(LOG_TAG, "stopAlarm called");
handler.removeCallbacks(alarmTest);
}
public void triggerAlarm() {
handler.post(alarmTest,0); //wait 0 ms and run
}
Depending on your OS you may find making your thread volatile may fix this.
private volatile Thread thread;
However - there are better ways to do this. One very useful one is using a small (just one entry) BlockingQueue which is polled by the running thread.
// Use a BlockingQueue to signal the alarm to stop.
BlockingQueue<String> stop = new ArrayBlockingQueue<>(1);
public void stopAlarm() {
stop.add("Stop");
}
public void triggerAlarm() {
new Thread(() -> {
try {
while (stop.poll(1, TimeUnit.SECONDS) == null) {
// Stuff
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
Clearly you will have to manage edge cases like where someone calls stopAlarm when no alarm is running.
As I am using gui and I need to create a thread to complete a task. See I want to display a dialog letting the user know the task has been completed I have tried
if(!thread.isAlive()) {
JOptionPane.showMessageDialog(null, "Done");
}
But that doesnt work.
Can anyone help me
Thanks
One option is to do your work using a SwingWorker. Override the done() method and have it notify your GUI that work is complete.
A simple example that nearly matches your use case is shown in the Javadocs at the top of the page:
final JLabel label;
class MeaningOfLifeFinder extends SwingWorker<String, Object> {
#Override
public String doInBackground() {
// Here you do the work of your thread
return findTheMeaningOfLife();
}
#Override
protected void done() {
// Here you notify the GUI
try {
label.setText(get());
} catch (Exception ignore) {
}
}
}
You could just have the thread print a message as it's last line of code in it's run method:
Thread thread = new Thread() {
#Override
public void run() {
//whatever you want this thread to do
//as the last line of code = the thread is going to terminate
JOptionPane.showMessageDialog(null, "Done");
}
}
thread.start();
If you want the main thread to wait for the thread to finish, in the main thread's code you'd use:
thread.join();
create a listener in your main Thread, and then program your Thread to tell the listener that it has completed.
public interface ThreadCompleteListener {
void notifyOfThreadComplete(final Thread thread);
}
then create the following class:
public abstract class NotifyingThread extends Thread {
private final Set<ThreadCompleteListener> listeners
= new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
#Override
public final void run() {
try {
doRun();
} finally {
notifyListeners();
}
}
public abstract void doRun();
}
NotifyingThread thread1 = new OneOfYourThreads();
thread1.addListener(this); // add ourselves as a listener
thread1.start(); // Start the Thread
then, as each Thread exits, your notifyOfThreadComplete method will be invoked with the Thread instance that just completed. So now you can run any of your code in this method.
Use Callable thread. It will return value,So we can identify that it completed its task.
My requirement is to have a thread that maintains a socket connection between a BlackBerry device and a server and exchanges commands, similar to request and response.
My problem is that I need to have this thread running in the background all the time and keep the UI available to the user. So, when there is a command from the server, this thread parses it and updates the UI and also if there's an action from the BlackBerry user, it sends it to the server and the server in turn handles it.
I developed the same application in Android using AsyncTask and it's working well. But in BlackBerry, as there's no such class, I used the invokeLater() option. The communication works fine between the server and the BB device, but the UI is frozen on the BlackBerry.
Anyone have any idea how to get this right?
Vishal is on the right track, but a little more is needed to match Android's AsyncTask. Since enums and generics aren't available with Java 1.3 on BlackBerry, you can't match the Android API perfectly.
But, you could do something like this (not tested ... this is just a starting point for you):
import net.rim.device.api.ui.UiApplication;
public abstract class AsyncTask {
public static final int FINISHED = 0;
public static final int PENDING = 1;
public static final int RUNNING = 2;
private int _status = PENDING;
private boolean _cancelled = false;
private Thread _worker;
/** subclasses MUST implement this method */
public abstract Object doInBackground(Object[] params);
protected void onPreExecute() {
// default implementation does nothing
}
protected void onPostExecute(Object result) {
// default implementation does nothing
}
protected void onProgressUpdate(Object[] values) {
// default implementation does nothing
}
protected void onCancelled() {
// default implementation does nothing
}
protected void onCancelled(Object result) {
onCancelled();
}
public final int getStatus() {
return _status;
}
public final boolean isCancelled() {
return _cancelled;
}
public final boolean cancel(boolean mayInterruptIfRunning) {
if (_status == FINISHED || _cancelled) {
return false;
} else {
_cancelled = true;
if (mayInterruptIfRunning && _status == RUNNING) {
// NOTE: calling Thread.interrupt() usually doesn't work
// well, unless you don't care what state the background
// processing is left in. I'm not 100% sure that this is how
// Android's AsyncTask implements cancel(true), but I
// normally just cancel background tasks by letting the
// doInBackground() method check isCancelled() at multiple
// points in its processing.
_worker.interrupt();
}
return true;
}
}
protected final void publishProgress(final Object[] values) {
// call back onProgressUpdate on the UI thread
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
onProgressUpdate(values);
}
});
}
private void completeTask(final Object result) {
// transmit the result back to the UI thread
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
// TODO: not sure if status should be FINISHED before or after onPostExecute()
_status = FINISHED;
}
});
}
public AsyncTask execute(final Object[] params) throws IllegalStateException {
if (getStatus() != PENDING) {
throw new IllegalStateException("An AsyncTask can only be executed once!");
} else {
try {
onPreExecute();
_worker = new Thread(new Runnable() {
public void run() {
try {
// run background work on this worker thread
final Object result = doInBackground(params);
completeTask(result);
} catch (Exception e) {
// I believe if Thread.interrupt() is called, we'll arrive here
completeTask(null);
}
}
});
_status = RUNNING;
_worker.start();
} catch (Exception e) {
// TODO: handle this exception
}
}
return this;
}
}
Also, it's important to keep in mind the Threading Rules for Android's AsyncTask, which apply to the above implementation, too:
Threading rules
There are a few threading rules that must be followed
for this class to work properly:
The AsyncTask class must be loaded on the UI thread. This is done
automatically as of JELLY_BEAN.
The task instance must be created on
the UI thread.
execute(Params...) must be invoked on the UI thread.
Do not call onPreExecute(), onPostExecute(Result),
doInBackground(Params...), onProgressUpdate(Progress...) manually.
The task can be executed only once (an exception will be thrown if a
second execution is attempted.)
You can create a Class that extends my implementation of class AsyncTask. Good Luck :)
Here the methods onPreExecute, onPostExecute are executed on UI thread and doInBackground is called on worker thread. Since onPreExecute, onPostExecute are abstract you can override them and provide your implementation like showing and dismissing progress dialog.
The sequence in which methods get's executed is
1) onPreExecute
2) doInBackground
3) onPostExecute
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
public abstract class AsyncTask {
Runnable runnable;
Thread threadToRun;
public abstract void onPreExecute();
public abstract void onPostExecute();
public abstract void doInBackground();
public void execute() {
try {
runnable = new Runnable() {
public void run() {
// TODO Auto-generated method stub
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
// TODO Auto-generated method stub
onPreExecute();
}
});
doInBackground();
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
// TODO Auto-generated method stub
onPostExecute();
}
});
}
};
threadToRun = new Thread(runnable);
threadToRun.start();
} catch (Exception e) {
// TODO: handle exception
Dialog.alert("Async Error Occured. " + e.toString());
}
}
}
I have two buttons and when the user click the first one it will start a thread to update the UI, and when the user click the second one the app will set a boolean variable for the first thread to not allow it to update the thread and then it will start the second one. This is my Runnable :
class MyRunnable implements Runnable {
boolean isUpdateEnabled = true;
#Override
public void run() {
// Retrieve list from Internet. takes about 10 sec to complete.
if (isUpdateEnabled) {
runOnUiThread(new Runnable() {
public void run() {
System.out.print("Update UI");
}
});
}
}
void enableUpdate(boolean enable) {
isUpdateEnabled = enable;
}
}
but since the thread will take a time to complete, if the user press the first button again can i check if the first thread is alive and then enable it to update the thread while guarantee that the code inside if (isUpdateEnabled) will execute if or what the right way to do it?
...
// on button click
if(thread.isAlive())
runnable.enableUpdate(true);
...
I suppose you will need to do two things here :
Synchnorize access to isEnableUpdate, because two different threads are accessing it.
You may want to break your code in public void run into smaller chunks, and check the isEnableUpdate variable every once in a while when you finish some logical piece of work or something like that.
Sample :
class MyRunnable implements Runnable
{
boolean isUpdateEnabled = true;
Object myUpdateLockObj = new Object();
#Override
public void run() {
// Retrieve list from Internet. takes about 10 sec to complete.
if (isUpdateEnabled) {
runOnUiThread(new Runnable() {
public void run() {
lock(myUpdateLockObj)
{
if (!isUpdateEnabled) return;
}
//do work in parts
System.out.print("Update");
lock(myUpdateLockObj)
{
if (!isUpdateEnabled) return;
}
// do work in parts
System.out.print(" UI");
}
});
}
}
void enableUpdate(boolean enable)
{
synhronized(myUpdateLockObj)
{
isUpdateEnabled = enable;
}
}
}