Looper.loop is ignored in approximately 20% cases - java

I have a worker thread that is running in the background. On this worker thread, I have a method called syncWithUiThreadAndWait. Here is the simplified code:
private void syncWithUiThreadAndWait(final Runnable codeToSync) {
if (looper == null)
throw new RuntimeException("Thread is not ready (Looper=null)");
if (looper != Looper.myLooper())
throw new RuntimeException("Called from wrong thread");
final boolean[] wasRun = {false};
new Handler(looper).post(new Runnable() {
// I use 'new Handler(looper).post' instead of direct call to make sure that this code will
// run 100% after Looper.loop() is called, because in some cases it can be called before Looper.loop
#Override
public void run() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
synchronized (MyWorkerThread.this) {
// Synchronization to establishes a happens-before relationship
wasRun[0] = true;
looper.quit();
}
}
});
}
});
Looper.loop();
synchronized (MyWorkerThread.this) {
// Synchronization to establishes a happens-before relationship
if (!wasRun[0])
throw new RuntimeException("WHY!!!");
}
}
So my question is: why sometimes this code runs correctly and sometimes thread loop does not start and I receive my 'WHY' exception?
Edit:
I decided to add some explanation to make it easier to understand.
What I am trying to do is a synchronized thread with UI thread.
First, prepare task new Handler (looper) .post (...); that will be run once I 'block' my background thread from continuing.
After that, I 'block' my background thread by Looper.loop ();
The task that I prepared will run once the loop is looped and will fire code for UI thread.
Lastly, at the end of the code that will be run on UI thread looper.quit (); is called to unblock background thread.

So even though I still don't know why it was happening. So if someone can explain I will mark it as a correct answer.
But I found a workaround using Thread.sleep() instead of using Looper.loop(). Wich works for me and probably is more efficient:
private void syncWithUiThreadAndWait(final Runnable codeToSync) {
synchronized (this) {
if (thread == null)
throw new RuntimeException("Thread not ready");
if (Thread.currentThread() != thread)
throw new RuntimeException("Called from wrong thread");
}
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
codeToSync.run();
setPaused(false);
}
});
setPaused(true);
final long sleepStart = System.currentTimeMillis();
while (isPaused()) {
try {
Thread.sleep(200);
} catch (InterruptedException ignored) { }
if (sleepStart + TIMEOUT_IN_MILLISEC <= System.currentTimeMillis())
throw new RuntimeException("Timeout waiting for network response");
}
}
private synchronized boolean isPaused() {
return paused;
}
private synchronized void setPaused(boolean newValue) {
paused = newValue;
}

Related

Can't stop thread

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.

How Java synchronize updates thread value?

I have next code:
boolean signal;
#Test
public void test() throws InterruptedException {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (!signal){
// empty loop body
}
}
});
thread.start();
Thread.sleep(1000);
signal = true;
thread.join();
}
It runs infinity loop due to creation of local copy of signal variable in thread. I know that I can fix it by making my signal variable volatile. But also loop can successfully exit if add synchronized block inside my loop (even empty):
boolean signal;
#Test
public void test() throws InterruptedException {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (!signal){
synchronized (this) {
}
}
}
});
thread.start();
Thread.sleep(1000);
signal = true;
thread.join();
}
How synchronized updates my signal value inside thread?
Synchronized does not updates the signal value itself, it basically just places a couple of flags to avoid two threads use the same object at the same time; something like: MonitorEnter and MonitorExit.
The first one locks the object, and the second one releases.
Take a look at the following article: how-the-java-virtual-machine-performs-thread-synchronization.
Please notice the article is very old; but as far as I understand the logic behind remains.

Method call from thread does not finish - How to end the thread - Workaround

I have a following code.
ReadWriteLock someLock = new ReentrantReadWriteLock();
Condition someCondition = someLock.writeLock().newCondition();
public someMethod() {
// do some stuff
someCondition.await(); //Lock here.
System.out.prinltn("This never prints");
}
public doSomeStuff() {
new Thread(new Runnable() {
#Override
public void run() {
try {
someMethod();
System.out.println("thread finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread is going to die");
}
}).start();
}
When the thread calls the method someMethod() it gets executed. But since there is an await() method on that function. It never ends / it does not print 'This never prints', unless its woken up by singnalAll(). But I want the thread to be finished once its executed.
I cannot refactor the whole thing. I just need a workaround to this problem. Its used in Swing application. So thread is important.
I think, this will do:
Thread thread =
new Thread(new Runnable() {
#Override
public void run() {
try {
someMethod();
System.out.println("thread finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread is going to die");
}
});
thread.start( );
final long reasonableTimeout = ...;
thread.join( reasonableTimeout );
// THIS WILL SHAKE IT UP
thread.interrupt( );
thread.join( );
// At this point, it is guaranteed that the thread has finished
I am not sure if I understood your question correctly but I think you want to start the someMethod() function and then make the caller exit without waiting for someMethod() to finish. This means you are basically branching your execution flow into two, one where the someMethod() running waiting for its due awakening and the other where the caller just continues on(which it will need to do if you want it to finish) after calling someMethod(). To do this you will have to run someMethod() in a separate thread. Something like this.
public doSomeStuff() {
new Thread(new Runnable() {
#Override
public void run() {
try {
new Thread(){
public void run(){
someMethod();
}
}.start();
System.out.println("thread finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread is going to die");
}
}).start();
}
Two ways you can sort this out.
1) Design your task with Interruption Policy
Do a defensive coding. If your task is interrupted by any means, the program should know how to deal with that.
2) Add a POISON PILL as in this example, Once you
public someMethod() {
while(condition predicate){
someCondition.await(TIME_OUT); //Lock here.
}
//ADD Poison pill here
System.out.prinltn("This never prints");
}
As Per Java Concurrency in Practice
When using condition waits (Object.wait or Condition.await):
1)Always have a condition predicate some test of object state that must hold before
proceeding;
2)Always test the condition predicate before calling wait, and again after returning from
wait;
3)Always call wait in a loop;
4)Ensure that the state variables making up the condition predicate are guarded by the lock
associated with the condition queue;
5) Hold the lock associated with the the condition queue when calling wait, notify, or
notifyAll; and
6)Do not release the lock after checking the condition predicate but before acting on it.

Running code on the main thread from a secondary thread?

This is a general Java question and not an Android one first off!
I'd like to know how to run code on the main thread, from the context of a secondary thread. For example:
new Thread(new Runnable() {
public void run() {
//work out pi to 1,000 DP (takes a while!)
//print the result on the main thread
}
}).start();
That sort of thing - I realise my example is a little poor since in Java you don't need to be in the main thread to print something out, and that Swing has an event queue also - but the generic situation where you might need to run say a Runnable on the main thread while in the context of a background thread.
EDIT: For comparison - here's how I'd do it in Objective-C:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0UL), ^{
//do background thread stuff
dispatch_async(dispatch_get_main_queue(), ^{
//update UI
});
});
Thanks in advance!
There is no universal way to just send some code to another running thread and say "Hey, you, do this." You would need to put the main thread into a state where it has a mechanism for receiving work and is waiting for work to do.
Here's a simple example of setting up the main thread to wait to receive work from other threads and run it as it arrives. Obviously you would want to add a way to actually end the program and so forth...!
public static final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
public static void main(String[] args) throws Exception {
new Thread(new Runnable(){
#Override
public void run() {
final int result;
result = 2+3;
queue.add(new Runnable(){
#Override
public void run() {
System.out.println(result);
}
});
}
}).start();
while(true) {
queue.take().run();
}
}
In case you are on Android, using a Handler should do the job?
new Handler(Looper.getMainLooper()).post(new Runnable () {
#Override
public void run () {
...
}
});
An old discussion, but if it is a matter of sending request to the main thread (an not the opposite direction) you can also do it with futures. The basic aim is to execute something in background and, when it is finished, to get the result:
public static void main(String[] args) throws InterruptedException, ExecutionException {
// create the task to execute
System.out.println("Main: Run thread");
FutureTask<Integer> task = new FutureTask<Integer>(
new Callable<Integer>() {
#Override
public Integer call() throws Exception {
// indicate the beginning of the thread
System.out.println("Thread: Start");
// decide a timeout between 1 and 5s
int timeout = 1000 + new Random().nextInt(4000);
// wait the timeout
Thread.sleep(timeout);
// indicate the end of the thread
System.out.println("Thread: Stop after " + timeout + "ms");
// return the result of the background execution
return timeout;
}
});
new Thread(task).start();
// here the thread is running in background
// during this time we do something else
System.out.println("Main: Start to work on other things...");
Thread.sleep(2000);
System.out.println("Main: I have done plenty of stuff, but now I need the result of my function!");
// wait for the thread to finish if necessary and retrieve the result.
Integer result = task.get();
// now we can go ahead and use the result
System.out.println("Main: Thread has returned " + result);
// you can also check task.isDone() before to call task.get() to know
// if it is finished and do somethings else if it is not the case.
}
If your intention is to do several stuff in background and retrieve the results, you can set some queues as said above or you can split the process in several futures (starting all at once or starting a new one when needed, even from another future). If you store each task in a map or a list, initialized in the main thread, you can check the futures that you want at anytime and get their results when they are done.
You may want to use the 'even dispatching thread' where most event driven things happen. If you are using swing then:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Your code here.
}
});
Or create a class that implements Runnable and pass it into invokeLater().
If you're using JavaFX, which I highly recommend, then you can use
Platform.runLater(new Runnable() {
#Override
public void run() {
alert(text);
}
});
from within your non-UI thread, and the runnable will executed from the UI thread on return from your thread.
A little late to the party but I think that my approach is a little bit different.
Modifying Affe's solution a little bit
public static final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
public static void main(String[] args) {
Thread myThread = new Thread(
() -> {
String name = Thread.currentThread().getName();
System.out.println("initial current thread " + name);
queue.add(() -> System.out.println(Thread.currentThread().getName()));
});
myThread.setName("background thread");
myThread.start();
try {
myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
while (!queue.isEmpty()) {
try {
queue.take().run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
output
initial current thread background thread
main

Java Thread won't stop

I have a JRuby engine which evaluates some scripts and I want to close the thread if it takes more than 5 seconds.
I tried something like this:
class myThread extends Thread{
boolean allDone = false;
public void threadDone() {
allDone = true;
}
public void run() {
while(true) {
engine.eval(myScript);
if(allDone)
return;
}
}
(...)
th1 = new myThread();
th1.start();
try {
Thread.sleep(5000);
if(th1.isAlive())
th1.threadDone();
} catch(InterruptedException e) {}
if(th1.isAlive())
System.out.println("Still alive");
I also tried to kill the thread with th1.stop() or th1.interrupt() but the value retured by th1.isAlive() method is always true.
What can I do?
I want to add that myScript could be "while(1) do; end" and I cannot wait until it's completed. So I want to prevent scripts like that and kill the thread if it takes more than 5 seconds.
Another solution would be to use the built-in mechanism to interrupt threads:
public void run() {
while (!Thread.currentThread().isInterrupted()) {
engine.eval(myScript);
}
}
...
th1 = new myThread();
th1.start();
try {
Thread.sleep(5000);
th1.interrupt();
}
This way, no need for an allDone field, and no risk in failing to synchronize.
To make your Thread stoppable you might want something like.
class MyTask implements Runnable {
public void run() {
try {
engine.eval(myScript);
} catch(ThreadDeath e) {
engine = null; // sudden death.
}
}
}
You can call Thread.stop(), but I suggest you read the warnings on this method first.
If you want a thread to run for up to 5 seconds, the simplest solution is for the thread to stop itself.
class MyTask implements Runnable {
public void run() {
long start = System.currentTimeMillis();
do {
engine.eval(myScript);
} while(System.currentTimeMillis() < start + 5000);
}
}
This assumes you want to run engine.eval() repeatedly. If this is not the case you may have to stop() the thread. It is deprecated for a good reason but it might be your only option.

Categories

Resources