When the user launches my Android App, I fire up 2 threads to do some processing in the background. thread_1 does some calculations on the client, and thread_2 fetches some data from the server. That all works fine. None of the threads modify the UI. I have two follow up questions.
new Thread(new Runnable(){
@Override
public void run(){
MyClass.someStaticVariable = doSomeCalculations();
}
}).start();
What is the best practice to retrieve the data from the run() method of a thread? I currently have a static variable, and I assi开发者_StackOverflowgn the relavent calculated data/ fetched data to it. Or is it recommended to use the Handler class to get data out of threads? I imagined one only uses the handler if they wish to update the UI.
while(true) { if (!thread1.isAlive() && !thread2.isAlive()) { startActivity(intent) } }
I need to wait until both threads are finished before I can pass the data from both threads via an Intent. How can I achieve that? I can do it using the code shown above, but that just seems wrong.
You could use a Future. It will block on get until the data is available: http://developer.android.com/reference/java/util/concurrent/Future.html
An alternative is to pass a CountDownLatch into the threads and call countDown() when exiting the run method: http://developer.android.com/reference/java/util/concurrent/CountDownLatch.html
final CountDownLatch latch = new CountDownLatch(2);
new Thread(new Runnable(){
@Override
public void run(){
// Do something
latch.countDown()
}
}).start();
new Thread(new Runnable(){
@Override
public void run(){
// Do something
latch.countDown()
}
}).start();
latch.await()
startActivity(intent)
Using callable / Future / ExecutorService would be the cleanest way of doing this in a reqular java app (should be same for android as well)
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> firstThreadResult = executor.submit(new Callable<Integer>() {
Integer call() {
}
});
Future<Integer> secondThreadResult = executor.submit(new Callable<Integer>() {
Integer call() {
}
});
executor.shutdown();
executor.awaitTermination(Integer.MAX_VALUE,TimeUnit.SECONDS); // or specify smaller timeout
// after this you can extract the two results
firstThreadResult.get();
secondThreadResult.get();
More detailed example.
You can use a shared object (via static field pointing to it or any other way), but you must be aware of two things. First there are synchronization issues with objects accessed by two threads. Use immutable objects to aleviate that. Second, how to notify the other thread that new shared data is available - this depends on what your other thread is doing.
Set common flag that both threads check or set when they finish. This way thread can check if other flag finished before it.
For query 1:
What is the best practice to retrieve the data from the run() method of a thread?
In addition to Future
, you can use Callback mechanism from your thread run()
method. In this run()
method, pass the value to caller object or set the relevant values in an object.
Implementing callbacks in Java with Runnable
For query 2:
I need to wait until both threads are finished before I can pass the data from both threads via an Intent
You can achieve it in multiple ways in addition basic join()
API.
1.ExecutorService invokeAll()
API
Executes the given tasks, returning a list of Futures holding their status and results when all complete.
2.CountDownLatch
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
3.ForkJoinPool or newWorkStealingPool()
in Executors
Refer to this related SE question:
wait until all threads finish their work in java
精彩评论