Set boolean from outside Thread, inside the Thread-run - java

I've got a boolean outside the Thread. Then I use a method that requires a Thread around it that returns a boolean. How can I set the boolean outside the thread with the returned boolean?
Code:
// Handle Automatic E-Mail Sending in a new Thread
new Thread(new Runnable() {
#Override
public void run() {
// Since we want to display a Toast from within a different Thread,
// we need to use the runOnUiThread to display it
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(ChecklistActivity.cActivity, D.T_SENDING_EMAIL, Toast.LENGTH_LONG).show();
}
});
/*TODO: emailSuccessfullySent = */EMailSender.SendEmail();
}
}).start();
I've read somewhere I could do it with a final array like so:
final boolean[] array = new boolean[1];
// Handle Automatic E-Mail Sending in a new Thread
new Thread(new Runnable() {
#Override
public void run() {
// Since we want to display a Toast from within a different Thread,
// we need to use the runOnUiThread to display it
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(ChecklistActivity.cActivity, D.T_SENDING_EMAIL, Toast.LENGTH_LONG).show();
}
});
array[0] = EMailSender.SendEmail();
}
}).start();
emailSuccessfullySent = array[0];
But I find this rather odd. Is this the generally accepted way to set a value from within a Thread, or is there a better way to do this?

It requires a little more overhead, but the best way to approach this problem in Android is to use a Handler. A Handler is a structure which you can use to receive messages from multiple threads and execute code on the thread the Handler is defined in. By overriding the handleMessage(Message msg) method and defining a few constants, you can send messages from any thread and have them be handled in your UI thread.
Code:
public boolean variable = false;
private class MyHandler extends Handler {
public static final int MESSAGE_TOAST = 1;
public static final int THREAD_RETURN = 2;
public void handleMessage(Message msg){
if(msg.what == MESSAGE_TOAST){
Toast.makeText(msg.getData().getString("toast"), Toast.LENGTH_LONG).show();
} else if(msg.what == THREAD_RETURN){
variable = msg.getData().getBoolean("returnValue");
}
}
}
public MyHandler handler = new MyHandler();
This would make your thread look like this:
// Handle Automatic E-Mail Sending in a new Thread
new Thread(new Runnable() {
#Override
public void run() {
Bundle bundle = new Bundle();
bundle.setString("toast","I want to display this message");
Message msg = handler.obtainMessage(MyHandler.MESSAGE_TOAST);
msg.setData(bundle);
msg.sendToTarget();
bundle.setBoolean("returnValue", EMailSender.SendEmail());
msg = handler.obtainMessage(MyHandler.THREAD_RETURN);
msg.setData(bundle);
msg.sendToTarget();
}
}).start();
It's a little confusing when you start using Handlers, but once you get to know them, they are easy and very powerful.

There is nothing special about setting the value of a non-synchronized variable inside a Thread. Since your boolean is declared "outside" the scope of your Thread, what you have done is a perfectly acceptable way of doing it. The point here is the scope of the boolean. You don't need to use an array, though. And the final qualifier is simply because variables declared outside the scope of an inner class cannot be accessed if they are not final.

Related

How do I avoid a handler.postDelayed(Runnable run) from being called?

I have this method to scan Bluetooth LE devices. The scanner runs asynchronously for 10s and then it is interrupted.
public void startScanning() {
Handler handler = new Handler();
final long SCAN_PERIOD = 10000;
handler.postDelayed(new Runnable() {
#Override
public void run() {
btScanner.stopScan(leScanCallback);
}
}, SCAN_PERIOD);
btScanner.startScan(leScanCallback);
}
However, depending on a condition that is verified during the scan (for example, I find a device I was looking for, etc.), I call btScanner.stopScan(leScanCallback). So I don't want to call the stopScan after SCAN_PERIOD otherwise I'd call it twice. How do I avoid the second call?
Try to remove call back:
handler.removeCallbacksAndMessages(null);
Handler handler = new Handler();
Runnable runnableRunner = new Runnable() {
#Override
public void run() {
btScanner.stopScan(leScanCallback);
}
}
public void startScanning() {
final long SCAN_PERIOD = 10000;
handler.postDelayed(runnableRunner, SCAN_PERIOD);
btScanner.startScan(leScanCallback);
}
Use removeCallbacks removes any pending posts of Runnable r that are in the message queue.
// cancel runnable whenever your condition is met.
handler.removeCallbacks(runnableRunner);
or use to remove all messages and callbacks
handler.removeCallbacksAndMessages(null);
I have another question on this problem.
I have a method m() in my "sequential" part of the code, not in the asynchronous one, that I need to call only if either the handler.removeCallbacksAndMessages(null); is called, or after the SCAN_PERIOD has expired. How do I check these conditions and basically wait that one of the two happens? Do I need to put m() in a synchronous run?
(Now I also have the global handler that I can use)

How to start a thread only if it is not executing or not started before, or only one instance of thread should be created

I have the following method, that called every time I click over a button, this results to start a new thread again and again when the button is pressed, that results to multiple initialisation of thread, however I want only one thread should get executed, how can I achieve this.
private void scheduleMessages() {
new Thread(new Runnable() {
#Override
public void run() {
//Some operations
}
}).start();
}
Note: this is a small method and I don't want to create a separate class, just to make it singleton, so a solution without singleton pattern will be appreciated.
if you cannot make instance of this to check isActive() you should make a semaphore variable - a boolean, that you set to true when you start thread and set to false when you are done.
private void scheduleMessages() {
if (!taskRunning){
new Thread(new Runnable() {
#Override
public void run() {
taskRunning = true;
//Some operations
taskRunning = false;
}
}).start();
}
}
Have that thread be a background thread - maybe initialize it when the button is pressed the first time.
Have that thread listen to a queue - and act upon messages in that queue.
Whenever the button is pressed again, put a new message into the queue.
If your need to execute every requests but on a specific number of threads, you can use a thread pool and let the executor manage the queue .
private ExecutorService services;
private final static int POOL_SIZE = 1;
public MessagesService(){
services = Executors.newFixedThreadPool(POOL_SIZE);
}
public void scheduleMessages(Runnable r){
services.submit(r);
}
If you call addCall x times, x thread will be executed at the end but will never use more than the number of thread available in the pool. Here, 1 thread.
For a system that only accept one request, you can use the same approch but check the Future returned by a single thread executor. That way, you can check the status of the service.
private ExecutorService services;
private Future<?> lastCall;
public MessagesService() {
services = Executors.newSingleThreadExecutor();
lastCall = null;
}
public synchronized void scheduleMessages(Runnable r) {
if(!isScheduled()){
lastCall = services.submit(r);
}
}
public boolean isScheduled(){
return lastCall != null && !lastCall.isDone();
}
That way, the Runnable doesn't need to update a flag, which give a reusable solution.
Here is a sample of the Runnable to test these codes :
new Runnable() {
System.out.println("Running");
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}

How can I write simple custom Android Handler class?

It's interesting for me how it's possible to write simple Android Handler class using only pure java to send signals from one thread to another?
I saw the source code:
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/os/Handler.java
But how for example to write class (Handler class) that can send for example int value from one thread to another(not using share data(like in Android Handler?))?
If you have the thread in the same method as the handler receiving the message you can do like this:
final Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
// do something
}
}
final Thread th = new Thread() {
public void run() {
// do something than send an integer - x in our case
int x = 0;
final Message msg = Message.obtain(handler, x, null);
handler.dispatchMessage(msg);
}
};
th.start();
If your handler can't be accessed directly from the thread than create a class extending Thread and pass the handler to the class's constructor.
This is how you can create your own CustomHandler like android handler by using only Java Api's .
private class CustomHandler {
private final Runnable POISON = new Runnable() {
#Override
public void run() {}
};
private final BlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<>();
public CustomHandler() {
initWorkerThread();
}
private void initWorkerThread() {
new Thread(new Runnable() {
#Override
public void run() {
Log.d("CustomHandler", "worker (looper) thread initialized");
while (true) {
Runnable runnable;
try {
runnable = mQueue.take();
} catch (InterruptedException e) {
return;
}
if (runnable == POISON) {
Log.d("CustomHandler", "poison data detected; stopping working thread");
return;
}
runnable.run();
}
}
}).start();
}
public void stop() {
Log.d("CustomHandler", "injecting poison data into the queue");
mQueue.clear();
mQueue.add(POISON);
}
public void post(Runnable job) {
mQueue.add(job);
}
}
And I would like to point at the question itself that you donot use handler to pass int values from one thread to another. Handlers are use to run tasks in another thread. If you want to share a variable between two threads, consider using volatile keyword and atomic variables.

Android cancel Thread

I am doing a simple Async operation with Android, but since I want to execute the action couple of times, I am not using AsyncTask, I instead use Thread/Runnable mechanism with Handler to handle messages and staff. But at one point when I need to execute the second operation, I need to cancel the previous operation if it is still active.
I have something like this:
private void exec() {
new Thread(new Runnable() {
public void run() {
mBind.exec(3);
}
}).start();
}
Then in exec(int a) I have an interation like:
for(int i = 0; i<=res.lenght; i++) {
updateGui();
}
But at one point the exec() method is called for second time, and the gui is updated with the previous results too (I need only the results from the new (2nd) request).
I know there is way to do this with FutureTask and play with cancel() or with Thread's 'throw ThreadDead' exception, but I am just curious if I can do it the same way I started in the first place.
thanks!
What I have understand from your question is that you want to cancel the currently running thread if the new thread started.
This you can do by calling Thread's interrupt() method, this will interrupt the currently running thread, and throws the InterruptedException.
Thread t1 = null;
private void exec() {
t1 = new Thread(new Runnable() {
public void run() {
mBind.exec(3);
}
}).start();
}
Before calling exec, call t1.interrupt().
Feels a bit dirty, but could you save the name of the most recently activated Thread and check for it in your Handler? Something like:
private static final int MESSAGE_UPDATE_COMPLETE = 0;
private String threadName;
private void exec() {
Thread thread = new Thread() {
public void run() {
// do stuff
...
Message msg = Message.obtain();
msg.what = MESSAGE_UPDATE_COMPLETE;
msg.obj = this.getName();
handler.sendMessage(msg);
}
};
thread.start();
threadName = thread.getName();
}
...
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
switch(msg.what){
case MESSAGE_UPDATE_COMPLETE:
if (threadName.equals((String)msg.obj)) {
// do UI update
}
break;
...
}
}
}

How do I ensure another Thread's Handler is not null before calling it?

My program threw a NullPointerException the other day when it tried to use a Handler created on another thread to send that thread a message. The Handler created by the other thread was not yet created, or not yet visible to the calling thread, despite the calling thread having already called start on the other thread. This only happens very rarely. Almost every test run does not get the exception.
I was wondering what the best way is to avoid this problem for sure with minimal complication and performance penalty. The program is a game and very performance sensitive, especially once it is running. Therefore I try to avoid using synchronization after setup, for example, and would prefer to avoid spinning on a variable at any time.
Background:
In Android the Handler class may be used to "enqueue an action to be performed on a different thread than your own". Documentation here:
http://developer.android.com/intl/de/reference/android/os/Handler.html
The Handler must be created on the thread where it will be used. So creating it in the constructor of a thread, which is run by the thread creating that thread, is not an option.
When the Handler is for a thread other than the UI thread, the Looper class must also be used:
http://developer.android.com/intl/de/reference/android/os/Looper.html
The documentation gives this example of using the two classes for this purpose:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
My very ugly workaround currently looks like this:
public class LooperThread extends Thread {
public volatile Handler mHandler;
public final ArrayBlockingQueue<Object> setupComplete = new ArrayBlockingQueue<Object>(1);
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
setupComplete();
Looper.loop();
}
public void waitForSetupComplete() {
while ( true ) {
try {
setupComplete.take();
return;
} catch (InterruptedException e) {
//Ignore and try again.
}
}
}
private void setupComplete() {
while( true ) {
try {
setupComplete.put(new Object());
return;
} catch (InterruptedException e) {
//Ignore and try again.
}
}
}
}
With the code in the creating thread looking like this:
LooperThread otherThread = new LooperThread();
otherThread.start();
otherThread.waitForSetupComplete();
otherThread.mHandler.sendEmptyMessage(0);
Are there any better solutions? Thanks.
I'd go with the classic wait/notify
public class LooperThread extends Thread {
private Handler mHandler;
public void run() {
Looper.prepare();
synchronized (this) {
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
notifyAll();
}
Looper.loop();
}
public synchronized Handler getHandler() {
while (mHandler == null) {
try {
wait();
} catch (InterruptedException e) {
//Ignore and try again.
}
}
return mHandler;
}
}
Handler returned from getHandler can then be used many times without invoking synchronized getHandler.
Preparing a Looper can block for a while, so I imagine you're hitting a condition where prepare() takes a moment to complete, thus mHandler is still undefined.
You could have your Thread extend HandlerThread, though even then you still have to wait to ensure the Looper has initialised. Perhaps something like this might work, where you have the Handler defined separately, but utilising the Looper of your custom thread.
Maybe.
private void setUp() {
mHandlerThread = new CustomThread("foo", Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
// Create our handler; this will block until looper is initialised
mHandler = new CustomHandler(mHandlerThread.getLooper());
// mHandler is now ready to use
}
private class CustomThread extends HandlerThread {
public void run() {
// ...
}
}
private class CustomHandler extends Handler {
CustomHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
// ...
}
}
I just want to add that the checked answer is the best one but if you test it like that is not going to work becouse you need to call super on run methode since it's in charge of preparing the looper so the code should be like this:
private void setUp() {
mHandlerThread = new CustomThread("foo", Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
// Create our handler; this will block until looper is initialised
mHandler = new CustomHandler(mHandlerThread.getLooper());
// mHandler is now ready to use
}
private class CustomThread extends HandlerThread {
public void run() {
super.run() // <- VERY IMPORTANT OTHERWISE IT DOES NOT WORK
// your code goes here
}
}
private class CustomHandler extends Handler {
CustomHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
// ...
}
}

Categories

Resources