I am running some async tasks and 1 of my users is crashing with a RejectedExecutionExemption:
Stack Trace
stackTrace: java.util.concurrent.RejectedExecutionException: Task android.os.AsyncTask$3#5e2675f rejected from java.util.concurrent.ThreadPoolExecutor#f5f25ac[Running, pool size = 9, active threads = 9, queued tasks = 128, completed tasks = 240]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2014)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:794)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1340)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:607)
The Line causing the exception
new SetDownloadStatusTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
Two Part question here really..
I'd like like some help understanding the first line of the exception:
ThreadPoolExecutor#f5f25ac[Running, pool size = 9, active threads = 9, queued tasks = 128, completed tasks = 240]
pool size vs. active threads vs quad tasks.. I assume I am executing too many tasks, but am unsure how to determine this really for those three variables. If someone could break that down for me, Id appreciate it.
If this is the case that I am running out of threads, should I increase the amount allowed and if so how, or is there a better solution.
Custom AsyncTask
private class SetDownloadStatusTask extends AsyncTask<Void, Void, DownloadStatus> {
#Override
protected DownloadStatus doInBackground(Void... params) {
return bookDownloadManager.status(product);
}
#Override
public void onPostExecute(DownloadStatus downloadStatus) {
updateMenuForDownloadStatus(downloadStatus);
}
}
I assume I am executing too many tasks
Correct.
If someone could break that down for me, Id appreciate it
AsyncTask.THREAD_POOL_EXECUTOR, on a quad-core CPU, will support nine parallel threads (pool size = 9). That is backed by a LinkedBlockingQueue of maximum length 128. And, you have requested your 138th simultaneous task, so we are out of threads (active threads = 9) and the queue is full (queued tasks = 128).
should I increase the amount allowed and if so how, or is there a better solution
You should be asking yourself "why in the name of all that is holy am I trying to download 138 things at once?".
If there is a legitimate need for that, use your own custom Executor, rather than THREAD_POOL_EXECUTOR. If there is not a legitimate need for 138+ simultaneous downloads — and, frankly, that number seems insane — then change your code to avoid doing that, such as cancelling tasks that you no longer need.
Related
I want to make 8 squares change colors between red/black periodically.
I acomplish this using timer.schedule with period time in milliseconds and it work
BUT then I realized that I need to use small time between this transitions (example nanoseconds).
To accomplish that I wrote this code:
timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run(){
//CODE OF THE TASK.
}
});
}
};
//To make schedule this task in 5 nanoseconds I use this!
exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleAtFixedRate(timerTask, 0, 5, TimeUnit.NANOSECONDS);
But when I run this, the UI is not updating (seems to be stuck), but in logcat, all the logs are printing very fast. How can I achieve to make a task periodically x nanoseconds?
The entire Android UI runs at 60Hz- 60 updates per second. This means the minimum time between redraws is 16 ms. You cannot run it at a higher framerate. Nor are human eyes capable of seeing changes at a much higher frequency than that.
iOS and most video game consoles also work on a 60 Hz refresh rate. You'd find very few to no systems that go faster.
I'm not sure what exactly you're trying to accomplish, but I'm fairly certain you're trying to do it the wrong way.
ALSO: I notice your timer task posts to a handler. That means your timer task is going to tell the main thread to run something, and the timer task is running in nanoseconds. YOu're basically going to choke your main thread full of "run this task" messages, then eventually crash with an OOM error when the event queue becomes so massive it can't add any more (which may take several minutes), because there's no way you're processing them fast enough with the thread switching overhead.
After doing a lot of research, I realized that in order to get the view to refresh so quickly, I needed the use of SurfaceView and a Thread to make the UI redraw very fast, I really had no knowledge of this. Thanks for the help
My Android app has to deal with arriving messages which frequently come in bunches (especially during periods of flaky connectivity). I handle these incoming messages in AsyncTasks so that I don't interfere with the UI thread. If too many messages come in at once, I get a RejectedExecutionException. My error stack looks like this:
10-22 14:44:49.398: E/AndroidRuntime(17834): Caused by: java.util.concurrent.RejectedExecutionException: Task android.os.AsyncTask$3#414cbe68 rejected from java.util.concurrent.ThreadPoolExecutor#412716b8[Running, pool size = 128, active threads = 22, queued tasks = 0, completed tasks = 1323]
10-22 14:44:49.398: E/AndroidRuntime(17834): at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1967)
10-22 14:44:49.398: E/AndroidRuntime(17834): at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:782)
10-22 14:44:49.398: E/AndroidRuntime(17834): at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1303)
10-22 14:44:49.398: E/AndroidRuntime(17834): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:564)
I'm running the tasks with task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) so that incoming messages are processed in parallel.
What is confusing about this, and different from related StackOverflow questions that I can find (e.g. here and here), is that the number of active threads and queued tasks don't seem to be bumping up against the limits (which seem to be 128 and 10, respectively). See the stacktrace:
ThreadPoolExecutor#412716b8[Running, pool size = 128, active threads = 22, queued tasks = 0, completed tasks = 1323]
Why would I be getting this error message?
Why would I be getting this error message?
If the ThreadPoolExecutor is still running, you would get this error message only if you have exceeded the number of tasks that can be queued by the ThreadPoolExecutor. The only time the RejectedExecutionException is thrown is by the ThreadPoolExecutor.AbortPolicy which is the default RejectedExecutionHandler.
To quote from the javadocs:
If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.
There is a maximum number of tasks. See this question/answer here: Is there a limit of AsyncTasks to be executed at the same time?
Here's a link for the sourcecode for AsyncTask.
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final BlockingQueue<Runnable> sWorkQueue =
new LinkedBlockingQueue<Runnable>(10);
private static final ThreadPoolExecutor sExecutor =
new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE,
KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);
So it looks like it starts at 5 threads, has a queue of 10. Once the queue is full it can start up to 128 threads. So it looks like you have exceeded 138 simultaneous requests.
ThreadPoolExecutor#412716b8[Running, pool size = 128, active threads = 22, queued tasks = 0, completed tasks = 1323]
Trying to catch the ThreadPoolExecutor the exact moment that it runs out of space is going to be very hard and it will quickly turn into a heisenbug in that the more you look at the ThreadPoolExecutor numbers, the more you are going to affect the synchronization of that class and therefore you might make the bug go away.
In your case, by the time you get to log the exception with the details about the TPE, the condition must have passed.
This exception also occur if your Executor call shutdown method and after that you give new Task (Runnable) for execution.
Like
mThreadPoolExecutor.shutdown();
...
...
...
mThreadPoolExecutor.execute(new Runnable(){...});
I was testing AsyncTask details and stumbled on the issue that when I start muliple tasks, the tasks 6 to 15 (10 tasks always) are in status RUNNING, but do not get into doInBackground (where the start time is set). The next 100 tasks are started immediately.
(source: beadsoft.de)
The tasks are started pretty simple:
int tasksToStart = TASKS_TO_ADD_ON_CLICK;
while (tasksToStart > 0) {
tasksToStart--;
mTask = new MyTask(TASK_RUNNING_TIME);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
mTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
mTask.execute();
tvTaskInfo.setText("Task " + mTask.id + " requested.");
}
This leads to the situation that all later started tasks have to be finished (meaning total running tasks is less than 5) before tasks 5 actually starts doing something.
a) Is there a way to force start the tasks?
b) Why is the status RUNNING if it does not do anything. Should it not be PENDING?
I do not have an android 4.x real device and cannot test there. In the emulator same limitations apply.
Anyone interested can download this sample project here.
If you wish to run multiple AsyncTasks more than 5 (which is the default Executor limit), you need to start it with a different Executor, like this:
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
The THREAD_POOL_EXECUTOR Allows you to execute up to 15 parallel AsyncTasks, whereas SERIAL_EXECUTOR only allows up to 5, in serial order.
I'm working on creating an app that allows very low bandwidth communication via high frequency sound waves. I've gotten to the point where I can create a frequency and do the fourier transform (with the help of Moonblink's open source code for Audalyzer).
But here's my problem: I'm unable to get the code to run with the correct timing. Let's say I want a piece of code to execute every 10ms, how would I go about doing this?
I've tried using a TimerTask, but there is a huge delay before the code actually executes, like up to 100ms.
I also tried this method simply by pinging the current time and executing only when that time has elapsed. But there is still a delay problem. Do you guys have any ideas?
Thread analysis = new Thread(new Runnable()
{
#Override
public void run()
{
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
long executeTime = System.currentTimeMillis();
manualAnalyzer.measureStart();
while (FFTransforming)
{
if(System.currentTimeMillis() >= executeTime)
{
//Reset the timer to execute again in 10ms
executeTime+=10;
//Perform Fourier Transform
manualAnalyzer.doUpdate(0);
//TODO: Analyze the results of the transform here...
}
}
manualAnalyzer.measureStop();
}
});
analysis.start();
I would recommend a very different approach: Do not try to run your code in real time.
Instead, rely on only the low-level audio code running in real time, by recording (or playing) continuously for a period of time encompassing the events of interest.
Your code then runs somewhat asynchronously to this, decoupled by the audio buffers. Your code's sense of time is determined not by the system clock as it executes, but rather by the defined inter-sample-interval of the audio data you work with. (ie, if you are using 48 Ksps then 10 mS later is 480 samples later)
You may need to modify your protocol governing interaction between the devices to widen the time window in which transmissions can be expected to occur. Ie, you can have precise timing with respect to the actual modulation and symbols within a "packet", but you should not expect nearly the same order of precision in determining when a packet is sent or received - you will have to "find" it amidst a longer recording containing noise.
Your thread/loop strategy is probably roughly as close as you're going to get. However, 10ms is not a lot of time, most Android devices are not super-powerful, and a Fourier transform is a lot of work to do. I find it unlikely that you'll be able to fit that much work in 10ms. I suspect you're going to have to increase that period.
i changed your code so that it takes the execution time of doUpdate into account. The use of System.nanoTime() should also increase accuracy.
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
long executeTime=0;
long nextTime = System.nanoTime();
manualAnalyzer.measureStart();
while (FFTransforming)
{
if(System.nanoTime() >= nextTime)
{
executeTime = System.nanoTime();
//Perform Fourier Transform
manualAnalyzer.doUpdate(0);
//TODO: Analyze the results of the transform here...
executeTime = System.nanoTime() - executeTime;
//guard against the case that doUpdate took longer than 10ms
final long i = executeTime/10000000;
//set the timer to execute again at the next full 10ms intervall
nextTime+= 10000000+ i*10000000
}
}
manualAnalyzer.measureStop();
}
What else could you do?
eliminate Garbage Collection
go native with the NDK (just an idea, this might as well give no benefit)
If I have code like:
Runnable r = ...;
Thread thread = new Thread(r);
thread.setPriority((Thread.MAX_PRIORITY + Thread.NORM_PRIORITY) / 2);
or ...
Runnable r = ...
Thread thread = new Thread( new Runnable() {
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_MORE_FAVORABLE);
r.run();
}
});
IS the android.os.Process way required/preferred?
WHY is the android.os.Process way preferred/required if it is?
This is not clearly documented as far as I can tell.
The current Dalvik implementation seems to map Java Threads one by one to the underlying linux system PTHREADs like you say. All Threads of all apps belong to the same thread group on the system, so every Thread competes with all Threads of all apps.
So currently Thread.setPriority should actually do the same thing as Process.setThreadPriority, using the smaller Java priority scale. The mapping of priorities is defined in kNiceValues at vm/Thread.c
Google uses
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
in Volley's Network Dispatcher thread, so I would believe that using Process.setThreadPriority() is the way to go.
I would rely on thread.setPriority(). The android.os.Process.setThreadPriority names a real thread priority of the underliying linux OS. However, those could, but doesn't need to map to Dalvik / Java VM threads, as the VM could do threading on its own means or use system threads or a combination of both. Raising the system priority would more likely result in prioritizing your application in favor of others, if not restricted by android security constraints, but not guarantee prioritizing your current Java Thread in favor of other Java Threads in your application.