I need to send a message to a HandlerThread from my current thread but stop the sendmessage call from returning immediately. Is there a way to do this sendMessage() in a blocking way?
This is what i think the solution should be.
// This handler will be associated with the UI thread
Handler uiHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
textView.setText("Progress: " + msg.what);
}
};
private void CreateThread() {
Thread t = new Thread() {
public void run() {
for(int i = 0; i < cnt; i++)
{
try {
Thread.sleep(1000);
} catch (Exception e) {
Log.v("Error: ", e.toString());
}
// You can update the UI by sending messages to the UI thread
uiHandler.sendMessage(uiHandler.obtainMessage(i));
}
}
}
};
t.start();
}
Please take a look at the Exchanger class. I would create an exchanger, send a Runnable having access to that exchanger, and synchronize on that exchanger. This way the exchanger would give me the results obtained asynchronously. You may think out something that would work with messages.
Note that a thread that calls Exchanger.exchange() may have to wait for a long time! (You may get an ANR if you call it from the UI thread.)
Related
I have this code:
public class classExample implements Observer Runnable {
public classExample() {
//...
}
#Override
public void run() {
while (true) {
//wait for EVENT;
//do something;
}
}
#Override
public void update(Observable arg0, Object arg1) {
//signal EVENT;
}
}
Basically, i want my thread to do something every time the update() method is called. I can't do in the update() method itself cause it would be executed in the same thread of the Observable calling notifyObservers().
Are there any ways to "signal" an event to the run() method?
You could implement message passing via blocking concurrent queues. The classExample thread could then wait blocking for new messages to be sent via the queue. This thread could then execute the stuff you originally wanted to execute in the update method, when a new message comes.
While the blocking queue as suggested by others would work, I'm not a big fan of it because it requires a busy wait (the consumer loops infinitely polling for a message). An alternative would be to submit a task every time the Observer receives a notification.
public class Main extends Observable implements Observer {
private final int numCores = Runtime.getRuntime().availableProcessors();
private final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numCores);
public Main() {
addObserver(this);
}
public static void main(String[] args) throws InterruptedException {
new Main().execute();
}
private void execute() {
for (int i = 0; i < 5; ++i) {
this.setChanged();
this.notifyObservers(i);
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
#Override
public void update(Observable o, Object arg) {
System.out.printf("Received notification on thread: %s.\n", Thread.currentThread().getName());
executor.submit(() -> System.out.printf("Running in thread: %s, result: %s.\n",
Thread.currentThread().getName(), arg));
}
}
Output:
Received notification on thread: main.
Running in thread: pool-1-thread-1, result: 0.
Received notification on thread: main.
Running in thread: pool-1-thread-2, result: 1.
Received notification on thread: main.
Running in thread: pool-1-thread-3, result: 2.
Received notification on thread: main.
Running in thread: pool-1-thread-4, result: 3.
Received notification on thread: main.
Running in thread: pool-1-thread-5, result: 4.
If you extend the thread class, you can override its methods and then you can just use super() and then do whatever code you want
At the very basic elements: Why not just use some membervariable/flag that you set in your update-Method?
eventWasFired = true;
In your while-loop inside of run() do something like:
try {
Thread.sleep(updateTimer);
if(eventWasFired) {
doSomeAction();
eventWasFired = false;
}
} catch (InterruptedException ie) {
// handle if you like
}
you need to synchronize access and use some atomic-variable if you have multiple threads that may access your observable. Otherwise your program is exposed to data races.
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.
I am working on an application in android. And I am trying to update data to UI from the background thread. However, it doesn't work for some reasons. Can any one splot the error or suggest any better solution? I used Thread to read data from the bluetooth socket and update the UI with RunOntheUI. Here is the code:
socket = belt.createRfcommSocketToServiceRecord(UUID_SECURE);
socket.connect();
stream = socket.getInputStream();
// final int intch;
Thread timer2 = new Thread() { // Threads - do multiple things
public void run() {
try {
// read data from input stream if the end has not been reached
while ((intch = stream.read()) != -1) {
byte ch = (byte) intch;
b1.append(ByteToHexString(ch) +"/");
decoder.Decode(b1.toString());
runOnUiThread(new Runnable() {
public void run()
{
// update the uI
hRMonitor.SetHeartRateValue((int) decoder.GetHeartRate());
}
});
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}};
timer2.start();
use
Your_Current_Activity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
hRMonitor.SetHeartRateValue((int) decoder.GetHeartRate());
}
});
instead of
runOnUiThread(new Runnable() {
public void run()
{
// update the uI
hRMonitor.SetHeartRateValue((int) decoder.GetHeartRate());
}
});
No. You MUST NOT do that. Never use another thread to update UI Thread, because UI Thread is not thread-safe, it means : when you update your UI Thread, UI Thread doesn't stop working for you do some stuff.
And Android has a machism for this work. This is Asyntask : it will create another thread and when need, it will has safe way to update UI Thread. If you want to more detail, Asyntask will drop a message to message queue of UI Thread.
Here is another link of my post about different Thread, Handler and Asyntask. Asyntask
Hope this help :)
Are there any Listeners in Java to handle that some thread have been ended?
Something like this:
Future<String> test = workerPool.submit(new TestCalalble());
test.addActionListener(new ActionListener()
{
public void actionEnd(ActionEvent e)
{
txt1.setText("Button1 clicked");
}
});
I know, that it is impossible to deal like this, but I want to be notified when some thread ended.
Usually I used for this Timer class with checking state of each Future. but it is not pretty way.
Thanks
There is CompletionService you can use.
CompletionService<Result> ecs
= new ExecutorCompletionService<Result>(e);
ecs.submit(new TestCallable());
if (ecs.take().get() != null) {
// on finish
}
Another alternative is to use ListenableFuture from Guava.
Code example:
ListenableFuture future = Futures.makeListenable(test);
future.addListener(new Runnable() {
public void run() {
System.out.println("Operation Complete.");
try {
System.out.println("Result: " + future.get());
} catch (Exception e) {
System.out.println("Error: " + e.message());
}
}
}, exec);
Personally, I like Guava solution better.
No. Such listener does not exist.
But you have 2 solutions.
Add code that notifies you that thread is done in the end of run() method
Use Callable interface that returns result of type Future. You can ask Future what the status is and use blocked method get() to retrieve result
Here is a geekish listener. Highly unadvisible to use but, funny and clever
Thread t = ...
t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
#Override
public void uncaughtException(Thread t, Throwable e) {
t.getThreadGroup().uncaughtException(t, e);//this is the default behaviour
}
protected void finalize() throws Throwable{
//cool, we go notified
//handle the notification, but be worried, it's the finalizer thread w/ max priority
}
});
The effect can be achived via PhantomRefernce better
hope you have a little smile :)
Side note: what you ask is NOT thread end, but task completion event and the best is overriding either decorateTask or afterExecute
Without adding a lot of extra code you can make a quick listener thread yourself as follows:
//worker thread for doings
Thread worker = new Thread(new Runnable(){
public void run(){/*work thread stuff here*/}
});
worker.start();
//observer thread for notifications
new Thread(new Runnable(){
public void run(){
try{worker.join();}
catch(Exception e){;}
finally{ /*worker is dead, do notifications.*/}
}).start();
You can implement Observer Pattern to report completion.
public interface IRunComplete {
public void reportCompletion(String message);
}
Let the Thread caller implement this interface.
and in run() method you call this method at the end. So now you exactly knows when this thread gonna end.
Try it. I am actually using this and it's working fine.
You have a join() method defined by Thread class for that. However, you don't have direct visibility to a thread executing your Callable in concurrency API case..
Use this Example:
public class Main {
public static void main(String[] args) {
CompletionListener completedListener = count -> System.out.println("Final Count Value: " + count);
HeavyWorkRunnable job = new HeavyWorkRunnable(completedListener);
Thread otherThread = new Thread(job);
otherThread.start();
}
static class HeavyWorkRunnable implements Runnable {
CompletionListener completionListener;
public HeavyWorkRunnable(CompletionListener completionListener) {
this.completionListener = completionListener;
}
#Override
public void run() {
int count = 0;
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Clock Tick #"+i);
count += 1;
}
if (completionListener != null) {
completionListener.onCompleted(count);
}
}
}
#FunctionalInterface
interface CompletionListener {
void onCompleted(int count);
}
}
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;
...
}
}
}