AsyncTasks do not get collected causing other AsyncTasks to not run - java

My app uses a lot of AsyncTasks. It is a web app after all. And when I keep track of the Debug tab, I notice every AsyncTask says running behind it and after 5 AsyncTasks, I can't start any AsyncTasks. I fixed it by changing the executor to THREAD_POOL_EXECUTOR which allows 15 threads to be pooled. But the AsyncTasks still show as running.
The AsyncTasks all have InputStreams in them and BufferedReaders in them to read the JSON, but I never call the close() method on the Streamers and Readers. Could this be it, or will the AsyncTask be collected after it's finished no matter what?
If that's the deal, then why can't I run more than 5 AsyncTasks in my app?
Seeing as I put a bounty on it, I will explain this more explicitly
The AsyncTasks all go through their methods. All of them are built the same exact way, except with different BasicNameValuePairs. I am 100% sure there is no easy mistake made in the code.
Here is an example of one of the AsyncTasks:
private class RunningEvent extends AsyncTask<Void, Void, Response> {
#Override
protected void onPreExecute() {
if (Constants.isOnline(getApplicationContext())) {
super.onPreExecute();
} else {
Toast.makeText(getApplicationContext(),
"No internet connection", Toast.LENGTH_LONG).show();
return;
}
}
#Override
protected Response doInBackground(Void... empty) {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(URL);
try {
List<NameValuePair> values = new ArrayList<NameValuePair>(5);
values.add(new BasicNameValuePair("tag", "eventRunning"));
values.add(new BasicNameValuePair("userid", String
.valueOf(response.user.userid)));
post.setEntity(new UrlEncodedFormEntity(values));
HttpResponse httpresponse = client.execute(post);
HttpEntity entity = httpresponse.getEntity();
InputStream stream = entity.getContent();
Log.i("MenuActivity",
"Input streamed, parsing Gson for existing events");
Gson gson = new Gson();
Reader reader = new InputStreamReader(stream);
eventresponse = gson.fromJson(reader, Response.class);
return eventresponse;
} catch (Exception e) {
e.printStackTrace();
Log.e("RunningEvent", "Error sending data to Server");
}
return null;
}
#Override
protected void onPostExecute(Response result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.i("MenuActivity", "Binding button");
if (eventresponse != null) {
if (eventresponse.success == 1) {
eventresponse.user = response.user;
bActivity.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Intent i = new Intent("com.xxx.xxx.EVENT");
i.putExtra("response", eventresponse);
running = false;
switcher.cancel(true);
MenuActivity.this.finish();
startActivity(i);
}
});
} else {
bActivity.setText("Nieuw activity");
bActivity.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Intent i = new Intent("com.xxx.xxx.NEWEVENT");
i.putExtra("response", response);
running = false;
switcher.cancel(true);
MenuActivity.this.finish();
startActivity(i);
}
});
}
} else {
Log.i("RunningEvent", "Response is null");
}
}
}
The example above is the sometimes gets runned as the 6th AsyncTask and it will never enter the doInBackground() method. I believe this is the 5 Thread limit of the SERIAL_EXECUTOR. I "fixed" the problem by putting most AsyncTasks in THREAD_POOL_EXECUTOR, but this is just avoiding it.
What could be the reason that these AsyncTasks never stop running and clogging up the Executor?

android.os.AsyncTask come with two built-in executor. if using SERIAL_EXECUTOR, there is no threadpool and all AsyncTask get execute one at a time in serial order. if using THREAD_POOL_EXECUTOR (I suppose this is what you refer in the question), this allows up to maximum 128 AsyncTask get execute in parallel.
The number 5 you refer and see from debugging is the corePoolSize of underlying threadpool (AKA. THREAD_POOL_EXECUTOR), which is different from maximumPoolSize. check out AsyncTask source code and see how threadpool is implemented:
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;
... ...
/**
* An {#link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
Check out ThreadPoolExecutor API to see what is the default threadpool behavior created by calling this constructor. Generally speaking, corePoolSize is the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set.
Those 5 AsyncTask you see in debug are actually on core threads which are finished and become idle but never terminated, you can alter this behavior by calling ThreadPoolExecutor.allowCoreThreadTimeOut(boolean).
More story on SERIAL_EXECUTOR
I said SERIAL_EXECUTOR does not use threadpool, this is not true. SERIAL_EXECUTOR is indeed delegate the real work to THREAD_POOL_EXECUTOR, but using ArrayDeque to control the submission of next tasks (next task is submitted iff the previous task is finished), check out the source:
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
So whatever you use SERIAL_EXECUTOR or THREAD_POOL_EXECUTOR, there are always 5 core threads shown in threadpool even they are finished and become idle. However, number of core thread (configured by corePoolSize) is not the number of threads (configured by maximumPoolSize) currently running in threadpool.

Related

How to wait for a Thread and Runnable using RequestFuture?

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]);
}
}

AsyncTask executes but only sometimes

So i use this code to call my AsyncTask
Log.d("before","make_connection");
new Make_Connection().execute();
Log.d("after","make_connection");
My class
private class Make_Connection extends AsyncTask<Void,Void,String>{
final int port = 4445;
#Override
protected void onPreExecute() {
Toast.makeText(KeyboardActivity.this,"This runs",Toast.LENGTH_LONG).show();
}
#Override
protected String doInBackground(Void... params) {
Log.d("Connection","Started");
Log.e("Connec","this runs");
try {
socket = new Socket(IP,port);
//dout = new DataOutputStream(socket.getOutputStream());
//dout.writeUTF("Connection Formed");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result) {
Toast.makeText(KeyboardActivity.this,"Connection Made",Toast.LENGTH_SHORT).show();
}
}
Now i can see in the android monitor that these two are always execute
Log.d("before","make_connection");
Log.d("after","make_connection");
But half of the time i cannot see the output produced by
Log.d("Connection","Started");
Log.e("Connec","this runs");
Even though onPreExecute() runs properly everytime.
I have tested on two diffent mobilies running 7.1 and 7.0
Can someone please tell me why this is happening
Try:
new Make_Connection().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
instead of only
new Make_Connection().execute();
This is needed, because in Android SDK 13 or higher they run serially by default. So if you want to run more than one AsyncTask simultaneously, use executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
For more details, see explanation under order of execution from This docs
AsyncTasks are run sequentially by default. They all execute on the same executor. Taken from here https://developer.android.com/reference/android/os/AsyncTask.html
If you truly want parallel execution, you can invoke
executeOnExecutor(java.util.concurrent.Executor, Object[]) with
THREAD_POOL_EXECUTOR.

Creating a callback on a class method

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).

Thread wait until a set of async tasks are finished

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.

Applying a Asynctask on a HttpClient

I haven't used an AsyncTask before neither do I understand some tutorials regarding it so I really don't know how to apply it on a HttpClient execution. Please kindly help me on this kind of implementation here's the initial code made:
public void commandModule(String url) {
try {
HttpClient httpClient = new DefaultHttpClient();
httpClient.execute(new HttpGet(url));
} catch (Exception e) {
}
}
#Override
public void onClick(View v) {
if (checkBox1.isChecked()) {
commandModule("http://192.168.1.102/?command1");
} else {
commandModule("http://192.168.1.102/?command2");
}
if (checkBox2.isChecked()) {
commandModule("http://192.168.1.102/?command3");
} else {
commandModule("http://192.168.1.102/?command4");
}
}
If you know about Thread in java, it will be easy for you to understand the working of Async Task in android. Basically, you can not perform any long running task on the main thread in android. It will block the main main thread and you will get ANR (Applicaton not responding) error. To avoid this you can either use thread or Async task.
Thread has one limitation, you can not update UI thread form any other thread. So, to update the UI you need to send message to main/UI thread using handler. You will have to do this every time you are implementing something using thread.
To simplify, android framework provide Async Task.
So, what ever you should put in the run() method of Thread, should go in doInBackground() method.
public void commandModule(String url) {
new RequestTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,url);
}
private class RequestTask extends AsyncTask<String,Void,Void>{
protected void doInBackground(String... args){
String url=args[0];
try {
HttpClient httpClient = new DefaultHttpClient();
httpClient.execute(new HttpGet(url));
} catch (Exception e) {
}
}
}
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
check this tutorial it will give ideas about your queries http://programmerguru.com/android-tutorial/android-asynctask-example/
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
public void commandModule(String url) {
try {
new RequestTask().execute(url);
} catch (Exception e) {
}
}
#Override
public void onClick(View v) {
if (checkBox1.isChecked()) {
commandModule("http://192.168.1.102/?command1");
} else {
commandModule("http://192.168.1.102/?command2");
}
if (checkBox2.isChecked()) {
commandModule("http://192.168.1.102/?command3");
} else {
commandModule("http://192.168.1.102/?command4");
}
}
private class RequestTask extends AsyncTask<String,Void,Void>{
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected void doInBackground(String... args){
String url=args[0];
try {
HttpClient httpClient = new DefaultHttpClient();
httpClient.execute(new HttpGet(url));
} catch (Exception e) {
}
}
#Override
protected void onPostExecute() {
}
}
onPreExecute() – Executed when execute() method is called inside commandModule() (In short When AsyncTask is triggered).
doInBackground() – Executed when onPreExecute() completed executing. Al the long task are handled here
onPostExecute() – Background job is finished

Categories

Resources