I've MyDataService which collects data by multiple GetSomeDataThread in parallel. Each GetSomeDataThread requests data synchronously via RequestFuture and StringRequest.
I got a timeout. I solved it by wrapping the request with another Thread and Runnable.
The timeout is gone, but I'm now getting the data asynchronously (see the comments in call()).
I found a lot of good answers on SO, but no duplicate.
Any ideas? Thanks in advance!
EDIT: To clarify the goal: result[0] should contain the content of future.get(), but it contains the default value "nothing". I probably need to wait for run() to finish, but don't know how.
EDIT 2: I can use a StringRequest (asynchronous) in call(), but not with future (synchronous). If I use StringRequest without wrapping it with another Thread, the app freezes and I'll get a timeout exception after a while (the URLs are fine).
public class MyDataService extends Service {
// ...
protected Summary summary;
protected void loadSummary() throws Exception {
Collection<GetSomeDataThread> threads = new ArrayList<>();
// loop
threads.add(new GetSomeDataThread("a"));
threads.add(new GetSomeDataThread("b"));
threads.add(new GetSomeDataThread("c"));
ExecutorService executorService = Executors.newFixedThreadPool(threads.size());
List<Future<JSONObject>> results = executorService.invokeAll(threads);
for (Future<JSONObject> result : results) {
// do something with the result:
// result.get()
}
executorService.shutdown();
}
}
-
public class GetSomeDataThread implements Callable<JSONObject> {
// ...
public GetSomeDataThread(String actionId) {
// ...
url += "&actionId=" + actionId;
}
#Override
public JSONObject call() throws Exception {
final String[] result = {"nothing"};
Thread t = new Thread(new Runnable() {
#Override
public void run() {
RequestFuture<String> future = RequestFuture.newFuture();
StringRequest request = new StringRequest(Request.Method.GET, url, future, future);
requestQueue.add(request);
result[0] = future.get();
Log.d(LOG_TAG, result[0]); // outputs the correct value, but delayed
Thread.currentThread().interrupt();
}
});
t.start();
// TODO: wait for thread + runnable to finish
// t.join(); just blocks
// result[0] equals "nothing"
return new JSONObject().put("result", result[0]);
}
}
Related
I'm struggling with a network connection class I've created. The result of the Runnable I create returns a JSON object that contains all the information needed from the server. The thread runs, and receives the data perfectly, but of course, the program keeps running in the meantime, which results in a JSONException as being NULL.
I created a class called NetworkManager, which has the following method (jsonResponse is initialized at the beginning of the class)
JSONObject jsonResponse;
public void createNetworkThread(Context context, final String requestURI, final RequestBody formParameters) {
Runnable runnable = new Runnable() {
#Override
public void run() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(requestURI).post(formParameters).build();
Response response = null;
try {
response = client.newCall(request).execute();
String stringResponse = response.body().string();
NetworkManager.this.jsonResponse = new JSONObject(stringResponse);
// This works perfectly, "message" is received and printed to the log //
Log.d("Net", NetworkManager.this.jsonResponse.getString("message"));
} catch (IOException e) {
Log.d("Net", "Failed");
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
The above is called from the Activity, as:
Net.createNetworkThread(SignupActivity.this, requestURI, formVars);
JSONObject jsonResponse = Net.jsonResponse;
The JSON object jsonResponse is returning as NULL because the Thread is still accessing the server for the response.
I need to figure out how to stop the jsonResponse Object from being populated by Net.jsonResponse until the thread completes in order to stop it from returning NULL.
Any help?
I would only agree to the comments on your question and let you know, what you can do here.
If you are creating a thread just to get of the main UI thread to do the Network call you probably want to use OkHttp feature which allows you to get the Network call off the thread and provides you with callbacks to get the result something like this. you can check some example here
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
}
#Override
public void onResponse(Response response) throws IOException {
// this is the callback which tells you the network call was successful, If like to make some changes to UI, you should call `runOnUiThread`.
"YourClassName".this.runOnUiThread(new Runnable() {
#Override
public void run() {
}
});
}
});
or you can use AsyncTask which also gets your job done off the main UI thread and gives you the result in the callbacks.
private class MyTask extends AsyncTask<Void, Void, Void> {
//you can change the Type Void, Void, Void here to something which you want
//First Void belongs to doInBackground(Void... avoid)
//Second Void belongs to onProgressUpdate(Void... progress)
//Third Void belongs to onPostExecute(Void result)
// you may change these as you fit,
//when you want to start this class with your argument you can do something like this.
//new MyTask().execute("your argument to doInBackground");
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
// this is the method where you provide your implementation for doing a task off the main UI thread.
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// in this callback you are back in the main UI thread to make changes to UI depending on your response
}
}
here is an example of AsyncTask
If you want to offload the main thread, you should consider that the parallel task could finish it's execution after, generally speaking, any amount of time. Sure, you can wait in the main thread for the child thread to finish (using 'join()'), though this is kind of questionable in terms of speed gain.
Anyway, answering your question:
I need to figure out how to stop the jsonResponse Object from being
populated by Net.jsonResponse until the thread completes in order to
stop it from returning NULL.
I suggest you change
public void createNetworkThread(...
to
public Thread createNetworkThread(...
{
...
Thread thread = new Thread(runnable);
thread.start();
return thread;
}
And consequently
Thread t = Net.createNetworkThread(SignupActivity.this, requestURI, formVars);
t.join(); // Wait until 't' finishes -- try-catch is omitted for the sake of demo.
JSONObject jsonResponse = Net.jsonResponse;
This, apparently, opens question of performance, since main thread will be effectively completely blocked by 't.join()' until the child thread will finish.
Answering the question in the topic: in Java 8 you can use lambda functional interface like this:
package multithreaded;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Multithreaded {
public static void main(String[] args) throws Exception {
Logger logger = LoggerFactory.getLogger("Main");
Worker<String, String> worker = new Worker<String, String>(
(String s) ->
{ // This is actual call-back code.
// It will be called by method 'apply' of interface 'Function' in the 'Worker'.
// It will accept String parameter and pass it in this block as variable 's'
logger.info("Embrace the beauty and power of Java 8! "+s); // yes, we can use local variables of the parent thread.
return "Call-Back "+s;
}
);
logger.info("Application starts new Worker.");
worker.start();
logger.info("Worker is running in background.");
Thread.currentThread().sleep(500); // Simulate some activity here...
logger.info("Result is unpredictable (could be null): "+worker.getResult());
// Wait here until worker is fully finished
worker.join();
logger.info("Result is predictable: "+worker.getResult());
}
}
Worker.java:
package multithreaded;
import java.util.function.Function;
public class Worker<T extends String, R extends String> extends Thread {
private final Function<T, R> callBack;
private volatile R result;
public Worker(Function<T, R> callBack)
{ this.callBack = callBack; }
#Override
public void run()
{
try{
int i = (int)(Math.random()*1000);
// simulate some activity unpredictable in terms of duration
Thread.currentThread().sleep(i);
// After "activity" is finished -- call the call-back function and get result in local variable.
// (Synchronization ommited for the sake of simplicity)
result = this.callBack.apply((T)("Result "+i)); // now let's call the call-back function and save the result in local variable.
}
catch(InterruptedException e)
{e.printStackTrace();}
}
// Getter for the local variable, populated by call-back function.
// (Synchronization ommited for the sake of simplicity)
public R getResult()
{ return this.result; }
}
Running above code multiple times, you will notice that from the parent thread's perspective the result is still unpredictable until the child thread is completely finished.
P.s. I suggest you re-think entire logic of data processing in your app and consider re-factoring towards entirely independent multi-threaded processing (perhaps using producer-consumer logic).
I have a set of HTTP reqeuests that each response adds an entry to ArrayList. Later I use that list to make some checks.
How can I make the program wait until all the requests are done and the list is filled before continuing to checks?
EDIT
code sample:
class BackgroundTask extends AsyncTask<Void,String,Void>{
List<Integer> responses;
#Override
protected synchronized Void doInBackground(Void... params) {
responses= new ArrayList<Integer>();
for( int i=0; i<10; i++ ){
restAPI.getNextInt( // SEND HTTP REQUEST
new Response.OnSuccess() { // ON SUCCESS CALLBACK
#Override
public void onResponse(Integer i) {
responses.add(i);
}},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}});
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
And in my main thread:
BackgroundTask bt = new BackGroundTask();
bt.execute();
bt.get(10000, TimeUnit.MILLISECONDS); // THIS DOESN'T WAIT
if( bt.responses.contains(10) ){
...
}
I didn't provided code before because I'm looking for the general solution not a specific for me
EDIT 2
Here is my second try that it didn't work. I put everything in the main thread.
final Semaphore sema = new Semaphore(-params.size()+1);
final List<Integer> responses = Collections.synchronizedList(new ArrayList<Integer>());
for( final Param p : params ){
new Thread(){
#Override
public void start(){
restAPI.nextInt(p, // SEND HTTP REQUEST
new Response.OnSuccess() { // ON SUCCESS CALLBACK
#Override
public void onResponse(Integer i) {
System.out.print("aaaaa");
sema.release();
responses.add(i);
}},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
sema.release();
}});
}
}.start();
}
try {
sema.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
if( responses.contains(10) )
...
Now what happens is that everything blocks/stops in sema.acquire() and aaaaa never prints. If I remove sema.acquire() then aaaaa prints.
The whole code is in a protected void onPostExecute(Void result) of an AsyncTask if this matters ...
Are you familiar with semaphores? Basically a semaphore has a number associated with it. Lets say you have five http requests to make. You will initialize the semaphore's number to -4. From your main thread that needs to wait for the list to be filled, call the acquire method on the semaphore. This will cause the thread to block (wait) until the semaphore's number has a value of 1. In each of your async threads, call "release" on the semaphore after the async thread is done adding its entry to the list. Each time you call release on the semaphore, the semaphore's number is incremented by 1. Thus when all of the async threads are finished, the semaphore will have a value of 1, allowing the main thread to continue executing. For future reference, calling acquire on the semaphore will decrement the value back to zero.
import java.util.concurrent.Semaphore;
Semaphore sema = new Semaphore(-4);
for each http request that needs to be made:
spawn a separate thread to execute this function {
do http request and insert entry into list
sema.release();
}
sema.acquire(); // block main thread until http requests are done
doStuff(); //The list is already filled, do whatever you need to do.
I have a simple application in which I create 3 threads inside a class to ping 3 different websites and note the time taken to do so.
I wish to enhance it by seeing which thread out of the 3 executes successfully first and terminating the other two .
Which class of the JDK would be helpful in doing so ? and how ?
Sample code to ping websites :
public static boolean pingUrl(final String address) {
try {
final URL url = new URL("http://" + address);
final HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
urlConn.setConnectTimeout(1000 * 10); // mTimeout is in seconds
final long startTime = System.currentTimeMillis();
urlConn.connect();
final long endTime = System.currentTimeMillis();
if (urlConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
System.out.println("Time (ms) : " + (endTime - startTime));
System.out.println("Ping to "+address +" was success");
return true;
}
} catch (final MalformedURLException e1) {
e1.printStackTrace();
} catch (final IOException e) {
e.printStackTrace();
}
return false;
}
I wish to enhance it by seeing which thread out of the 3 executes successfully first and terminating the other two .
I would use an ExecutorService combined with a ExecutorCompletionService. Then, when the first Future is returned from the completion service when the first task completes, you would call shutdownNow() on the ExecutorService.
The javadocs for ExecutorCompletionService are pretty good and show how to use it.
// maybe you want 10 threads working on your tasks
ExecutorService threadPool = Executors.newFixedThreadPool(10);
CompletionService<Result> ecs
= new ExecutorCompletionService<Result>(threadPool);
for (Callable<Result> task : tasks) {
// submit your tasks to the completion service, they run in the thread-pool
ecs.submit(task);
}
// once you get one result
Future<Result> future = ecs.take();
// kill the rest of the tasks
threadPool.shutdownNow();
Result result = future.get();
// probably will need to close the thread connections, see below
// maybe call threadPool.awaitShutdown(...) here to wait for the others to die
The only problem with this mechanism is that this will only interrupt the threads. In your case they are going to be stuck in urlConn.connect(); which is not interruptible. Once the ecs.take() returns, you are going to have to run back over your tasks and call disconnect() on the the HttpURLConnection that are still in progress. Even then I'm not sure if it will stop a connection that is currently underway. If that doesn't work then you may need to switch to using Apache HttpClient or some other class that you can close to stop the threads from waiting longer.
for (Callable<Result> task : tasks) {
// you'll need to do something like this
task.closeConnection();
}
In your case, your task might look something like:
public class MyPingTask implements Callable<Boolean> {
private String address;
public MyPingTask(String address) {
this.address = address;
}
public Boolean call() throws Exception {
// obviously the pingUrl code could go right here
return pingUrl(address);
}
}
Here is the Java tutorial on ExecutorService and related classes.
I suppose BlockingQueue may be useful. The main idea that spawned thread writes some value to BlockingQueue when finished and gracefully closes on InterruptedException
For example:
public void runPing(List<String> urls) {
Collection<Thread> runningThreads = new ArrayList<>(urls.size());
final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(urls.size());
for (int i = 0; i < 3; i++) {
final String url = urls.get(i);
Thread t = new Thread(new Runnable() {
public void run() {
pingUrl(url);
queue.add(1);
}
});
runningThreads.add(t);
}
try {
queue.poll(1, TimeUnit.HOURS);
interruptChilds(runningThreads);
} catch (Exception e) {
interruptChilds(runningThreads);
}
}
private void interruptChilds(Collection<Thread> runningThreads) {
for (Thread t : runningThreads) {
t.interrupt();
}
}
Please note that in there are no handling of InterruptedException. It should be added in your method
I'm using a 3rd party function (say runThird()) that has a tendency to loop indefinitely and has no timeout facility built in. However, I can kill it (killThird()). Is there a proper way to do this (i.e. some concurrency construct)?
Here's my attempt at this:
java.lang.Thread thread = new Thread(new Runnable(){
#Override
public void run(){
try {
Thread.sleep(TIMEOUT);
} catch (java.lang.InterruptedException e){
return;
}
killThird();
}
});
thread.start();
RunThirdResult rtr = runThird();
if (thread != null){
thread.interrupt();
}
But I'm not sure I like the overhead of creating a thread, using sleep and the contrivance of interrupting the thread if runThird() returns.
Let's assume runThird() retuns Integer ...
// ... in your class ...
private ExecutorService executor = Executors.newCachedThreadPool();
//... then somewhere, where you want to call runThird()
Future<Integer> handle = executor.submit( new Callable<Integer>(){
#Override Integer call(){
return runThird(); // Assume you made it available here ...
}
}
Integer result;
try{
result = handle.get(TIMEOUT,UNIT); // TIMEOUT and UNIT declared somewhere above ...
}
catch(TimeoutException ex) {
killThird();
// HANDLE result not being set!
}
// ... use result.
I would use a ScheduledExecutorService for this. Schedule it to be killed.
volatile RunThirdResult rtr;
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.schedule(new Runnable(){
public void run(){
if(rtr == null) killThird();
}
}, TIMEOUT_IN_MILLIS, TimeUnit.MILLISECONDS);
RunThirdResult rtr = runThird();
Something like that? The most interesting part is StoppableWrapper#stop(), cause graceful cancellation is a hard thing and there's no common approach for all cases. One time you need to clear filesystem, other time to close network connection, etc. In your sample, you just call interrupt(), so I assumed runThird() honors being interrupted and will take care to clean things behind itself.
class Sample {
final ExecutorService tasksExecutor = Executors.newCachedThreadPool();
class StoppableWrapper implements Runnable {
private final Runnable task;
private final CountDownLatch executed;
StoppableWrapper(Runnable task, CountDownLatch executed) {
this.task = task;
this.executed = executed;
}
void stop() {
// e.g. Thread.currentThread().interrupt()
}
#Override
public void run() {
task.run();
executed.countDown();
}
}
public void scheduleTimingOutTaskExecution(final long timeout) {
final CountDownLatch executed = new CountDownLatch(1);
final StoppableWrapper command = new StoppableWrapper(new RunThirdInstance(), executed);
tasksExecutor.execute(command);
tasksExecutor.execute(new Runnable() {
#Override
public void run() {
try {
if (!executed.await(timeout, TimeUnit.MILLISECONDS)) {
command.stop();
// additionally, you can make stop() return boolean after time-out as well and handle failure
}
} catch (InterruptedException e) {
// handle stopper exception here
}
}
});
}
}
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;
...
}
}
}