Update UI in Java ThreadPool - java

I do some network request simultaneously and get the response using HTTPClient in Android. I am using threadsafeclientconnmanager in order to have thread safe connection.
In order to do it simultaneously I am using Java ThreadPool.
private enum STATE { state1, state2, state3 };
ExecutorService executor = Executors.newFixedThreadPool(nThreads);
and submit 3 runnable:
executor.submit(new Processor(state1));
executor.submit(new Processor(state2));
executor.submit(new Processor(state3));
And this Processor class which extends runnable:
class Processor implements Runnable {
private STATE state;
public Processor(STATE state) {
this.state = state;
}
#Override
public void run() {
switch (state) {
case state1:
// Do something
// Call Back to update UI
break;
case state2:
// Do something
// Call Back to update UI
break;
case state3:
// Do something
// Call Back to update UI
break;
}
latch.countDown();
}
}
As you see in the run method, for every state, I do some instruction and then I need to update UI using callBack methods.
And since that is UI thread every callback method should be :
runOnUiThread(new Runnable() {
#Override
public void run() {
//Update UI
}
});
Is there any better solution to update UI when we are having Java thread pool in Android?

You should exec the network connection in other thread, never in main UI thread. When you will have new data, you send it from network thread to main thread.
You can use AsyncTask or Handler.
http://developer.android.com/reference/android/os/AsyncTask.html
https://developer.android.com/training/multiple-threads/communicate-ui.html
Asynctask has "updatePublish" to send data to UI Thread.
Handler is a message system to send data to UI Thread and vice versa
I think that Handler is the better option for you.

Related

What are the thread command alternatives in Java?

I am dealing with threads and I want to run this code whenever I open Cal_JInternalFrame. It runs the fist time, but whenever I reopen the frame, it doesn't run again. I use t1.interrupted() at exit time of the whole application. The code is:
Thread t1 = new Thread( new Runnable() {
#Override
public void run() {
while ( !t1.isInterrupted() ) {
// ......... Oil Calculation Thread ...
int price = (Integer.parseInt(jLabel22.getText()));
int qty = (Integer)jSpinner8.getValue();
int totalOil =qty * price;
jTextField19.setText(String.valueOf(totalOil));
}
}
});
t1.start() is in the constructor of the main frame.
The thread primitive methods destroy(), stop(), resume(), and suspend() have been deprecated, so I can't use those. How can I stop and resume a thread now? And if my thread t1 is interrupted, how can it be resumed or run again?
Threads cannot be re-used. For tasks that require to be executed on a separate thread at different times, use a single thread executor.
It seems like you need a worker thread. Since standard threads are not reusable without extra work, we use worker threads to manage tasks that should be executed multiple times.
ExecutorService executors = Executors.newSingleThreadExecutor();
With this, you can reuse a single thread to execute code multiple times. It also allows you to make asynchronous callbacks using Future like this:
class Demo {
static ExecutorService executor = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
Future<String> result = executor.submit(new Callable<String>() {
public String call() {
//do something
return "Task Complete";
}
});
try {
System.out.println(result.get()); //get() blocks until call() returns with its value
}catch(Exception e) {
e.printStackTrace();
}
}
}
You can now re-use executor for the task that you want. It accepts Runnable through it's execute(Runnable) method.
I see you're using Swing. Post all swing code to the Event Dispatch Thread using EventQueue.invokeLater(Runnable). getText() and setText() should be called on the Event Dispatch Thread to avoid inconsistancies.
How can I stop and resume a thread now?
You can't. Instead, you need to make your thread stop and resume itself. For example:
private boolean wake;
public synchronized void wakeup() {
this.wake = true;
this.notify();
}
public void run() {
while ( !t1.isInterrupted() ) {
// do stuff ...
wake = false;
synchronized (this) {
while (!wake) {
try {
this.wait();
} catch (InterruptedException ex) {
t1.interrupt(); // reset the interrupted flag
}
}
}
}
}
When some other thread wants to get this one to do something, the calls the wakeup() method on the extended runnable object.
And if my thread t1 is interrupted, how can it be resumed or run again?
As you have written it, No. Once the thread returns from the run() method call, it cannot be restarted. You would need to create and start a brand new Thread.
However, what you are trying to do is unsafe. As #Erwin points out, it is not safe for the t1 thread to be calling methods on Swing objects such as jTextField19. You should only call methods on Swing objects from the Swing event dispatching thread.
Reference:
Concurrency in Swing

Capturing executor for current thread

I'm using ListenableFuture from Guava, and one nice thing about them is that one pass Executor to the Futures.addCallback method, that is, ask to execute the callback on a given thread/executor.
In my Android application, I want to be able to start the asynchronous execution based on ListenableFuture in the UI thread, and schedule a callback which is also executed also on the UI thread. Therefore, I'd like to somehow submit the UI thread executor to the Futures.addCallback method mentioned above. How to achieve that?
Or, in other words, I want to have an executor for the UI thread. Is it available already in Android, or, if I have to create my own, how do I do that?
EDIT: As an extension to this question, is it possible to do same thing, but not just with UI thread, but with any particular thread, where the call to async method is made?
I would be happy to know how to achieve the same effect without resorting to the Android-specific stuff like Handler and Looper, just with pure Java.
I think I've see some implementation doing that. The basic Idea is roughly
class UiThreadExecutor implements Executor {
private final Handler mHandler = new Handler(Looper.getMainLooper());
#Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
You can delegate to run anything in the main thread by passing it to a handler for the main thread.
Edit: https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit/android/MainThreadExecutor.java for example
Edit2: You can configure the handler like e.g. SensorManager#registerListener(..., Handler handler) allows you to do.
class HandlerThreadExecutor implements Executor {
private final Handler mHandler;
public HandlerThreadExecutor(Handler optionalHandler) {
mHandler = optionalHandler != null ? optionalHandler : new Handler(Looper.getMainLooper());
}
#Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
The advantage over using the current thread's looper is that it makes it explicit which Looper you use. In your solution you take the Looper of whatever thread calls new ExecuteOnCaller() - and that's often not the thread you run code in later.
I would be happy to know how to achieve the same effect without resorting to the Android-specific stuff like Handler and Looper, just with pure Java.
Looper, Handler and the message queue behind all that logic are made of mostly pure Java. The problem with a generic solution is that you can't "inject" code to run into a thread. The thread must periodically check some kind of task queue to see if there is something to run.
If you write code like
new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("Hello");
}
}
}).start();
Then there is no way to make that thread do anything else but constantly print "Hello". If you could do that it would be like dynamically inserting a jump to other code into the program code. That would IMO be a terrible idea.
final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
Runnable codeToRunInThisThread = queue.take();
codeToRunInThisThread.run();
}
} catch (InterruptedException ignored) {}
}
}).start();
On the other hand is a simple thread that loops forever on a queue. The thread could do other tasks in between but you have to add a manual check into the code.
And you can send it tasks via
queue.put(new Runnable() {
#Override
public void run() {
System.out.println("Hello!");
}
});
There is no special handler defined here but that's the core of what Handler & Looper do in Android. Handler in Android allows you to define a callback for a Message instead of just a Runnable.
Executors.newCachedThreadPool() and similar do roughly the same thing. There are just multiple threads waiting on code in a single queue.
As an extension to this question, is it possible to do same thing, but not just with UI thread, but with any particular thread, where the call to async method is made?
The generic answer is No. Only if there is a way to inject code to run in that thread.
Based on asnwer from #zapl, here is my implementation, which also answers the edited (extended) question: https://gist.github.com/RomanIakovlev/8540439
Figured out I'll also put it here, in case if link will rot some day:
package com.example.concurrent;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Executor;
/**
* When the calling thread has a Looper installed (like the UI thread), an instance of ExecuteOnCaller will submit
* Runnables into the caller thread. Otherwise it will submit the Runnables to the UI thread.
*/
public class ExecuteOnCaller implements Executor {
private static ThreadLocal<Handler> threadLocalHandler = new ThreadLocal<Handler>() {
#Override
protected Handler initialValue() {
Looper looper = Looper.myLooper();
if (looper == null)
looper = Looper.getMainLooper();
return new Handler(looper);
}
};
private final Handler handler = threadLocalHandler.get();
#Override
public void execute(Runnable command) {
handler.post(command);
}
}
My pattern to use it would be like this:
/**
* in SomeActivity.java or SomeFragment.java
*/
Futures.addCallback(myModel.asyncOperation(param), new FutureCallback<Void>() {
#Override
public void onSuccess(Void aVoid) {
// handle success
}
#Override
public void onFailure(Throwable throwable) {
// handle exception
}
}, new ExecuteOnCaller());
Use com.google.android.gms.tasks.TaskExecutors.MAIN_THREAD.
An Executor that uses the main application thread.
Source: Android docs
The tasks APIs are part of Google Play services since version 9.0.0.
For Android UI thread executor use:
ContextCompat.getMainExecutor(context)
To address your question and extended question to create an Executor that simply runs on the current thread and avoids Android classes:
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
See documentation: https://developer.android.com/reference/java/util/concurrent/Executor

Single Android Thread for Multiple Jobs

I would like to have an application which either loads or saves data through a HTTP request, however the data must interact with the UI thread. Ideally, I would like a single thread to use an IF statement on a message to determine if the request is to "load" or "save".
What would be the simplest way of doing this with the smallest amount of code?
Also, do instances of Handlers run on individual threads?
EDIT: This is the code I am using now:
Handler doStuff = new Handler(){
#Override
public void handleMessage(Message msg){
if(msg.what == 1){
// Load all the information.
// Get the ID from sharedPrefs
SharedPreferences details= getSharedPreferences("details", 0);
String ID = patDetails.getString("id", "error");
// Load up the ID from HTTP
String patInfo = httpInc.getURLContent("info.php?no="+AES.encrypt("387gk3hjbo8sgslksjho87s", ID));
// Separate all the details
patientInfo = patInfo.split("~");
}
if(msg.what == 2){
// Save the data
}
}
};
Eclipse halts the debugging and displays, "Source not found" for StrictMode.class
I suppose it's because it's using the Main thread to access the internet although it's running in individual threads.
Any idea.
Handlers do run on individual threads. Check that link. You should also check out AsyncTask.
I would propose submitting the jobs as Runnable to a single-threaded ExecutorService:
public class SomeClass {
private ExecutorService execService = Executors.newSingleThreadExecutor();
public void doSomething() {
final String someUiData = // retrieve data from UI
execService.submit(new Runnable() {
#Override
public void run() {
// so something time-consuming, which will be executed asynchronously from the UI thread
// you can also access someUiData here...
}
});
}
}
This way, the UI thread will not block whereas you can easily submit a different Runnable for different operations and the ExecutorService will completely take care of keeping it async.
Edit: If you need to interact with the UI, do so before becoming asynchronous and keep the result in final variables.

Showing ok cancel Dialogbox through thread

I have an Android service which spawns a thread.This thread waits for network data and after receiving that data I want to show Ok Cancel Dialogbox.
I was getting exception can't create handle that should have Looper.prepare().I added Looper.prepare() and Looper.loop() then now I am not getting any exception but its waiting infinitely.
Instead of using a sole thread it's better to use an AsyncTask which is also a speacialized thread for Android.
You can wait for data in the AsyncTask's doInBackGround method and when you received data you can call publishProgress() which will invoke onProgressUpdate method of AsyncTask.
At onProgressUpdate you can update the UI without blocking the main thread and also this is the preferred way of doing long time operations in background like network listening etc.
Check AsyncTask for more info and how to use it.
http://developer.android.com/reference/android/os/AsyncTask.html
You can invoke the UI thread(showing alert dialog) in non-UI thread by using handlers as like below code
new Thread(new Runnable()
{ public void run()
{
try {
///do your stuff in
mHandlerShowDialog.post(mUpdateShowDialog);
///do your struff
}
} ).start();
final Handler mHandlerShowDialog= new Handler();
final Runnable mUpdateShowDialog = new Runnable() {
public void run() {
// show your dialog here
}
};

Cancel the Runnable in the .runOnFirstFix() method of LocationOverlay Object

I have an application the leans heavily on map functionality. From the first Activity I call the runOnFirstFix() method to load a lot of data from a database once the location of the user has been found, but I also want to be able to interrupt this runnable and stop it mid execution for when I switch activity or the user presses the button to stop it running.
myLocationOverlay.runOnFirstFix(new Runnable() {
public void run() {
mc.animateTo(myLocationOverlay.getMyLocation());
mc.setZoom(15);
userLatitude = myLocationOverlay.getMyLocation().getLatitudeE6();
userLongitude = myLocationOverlay.getMyLocation().getLongitudeE6();
userLocationAcquired = true;
loadMapData(); //Here the method is called for heavy data retrieval
}
});
How can I stop this Runnable mid execution?
You could (and probably should) use an AsyncTask
private class MapLoader extends AsyncTask<Void, Void, Data> {
#Override
protected Data doInBackground(Void... params) {
return loadMapData(); //Here the method is called for heavy data retrieval, make it return that Data
}
#Override
protected void onPostExecute(Data result) {
//do things with your mapview using the loaded Data (this is executed by the uithread)
}
}
and then in replace your other code with
final MapLoader mapLoader = new MapLoader();
myLocationOverlay.runOnFirstFix(new Runnable() {
public void run() {
mc.animateTo(myLocationOverlay.getMyLocation());
mc.setZoom(15);
userLatitude = myLocationOverlay.getMyLocation().getLatitudeE6();
userLongitude = myLocationOverlay.getMyLocation().getLongitudeE6();
userLocationAcquired = true;
mapLoader.execute();
}
});
then you should be able to cancel the running task when you no longer want it to complete using
mapLoader.cancel(true);
I hope the code compiles, I haven't tested it, but it should work :)
Just make sure that it is the ui thread that creates the MapLoader
edit: I think you need to wrap the mapLoader.execute(); call in a runOnUiThread() call in order for it to work correctly since runOnFirstFix() might spawn a new thread
use the handler object to handle this runnable.
define this runnable with the runnable object.
after that in handler you can start the cancel this runnable service
for e.g.
Handler handler = new Handler();
on startCommand()
handler.postDelayed(myRunnable,5000);
this will execute the run method of runnable after 5 sec
for cancel
handler.removeCallbacks(myRunnable);
and your runnable define like this way
private Runnable myRunnable = new Runnable(){
public void run(){
// do something here
}
}
http://developer.android.com/reference/android/os/Handler.html
http://developer.android.com/reference/java/util/logging/Handler.html
http://www.vogella.de/articles/AndroidPerformance/article.html
In Java, you can call interrupt() on a running thread which should stop the execution of given thread. But if any kind of blocking operation like wait() or join() is being performed, InterruptedException will be thrown. Even some kinds of socket-related blocking operations can lead to InterruptedIOException under Linux, or under Windows the operation still remains blocked (since Windows does not support interruptible I/O). I think you still could interrupt your runnable, just be aware that some I/O may not be interrupted until finished and if blocking, it might throw those kind of exceptions I mentioned.

Categories

Resources