I am working on application (Matt's traceroute windows version http://winmtr.net/) which creates multi threads each thread has its own process (which execute ping command). ThreadPoolExecutor
shutdown all threads after some time( e.g.10 seconds)
ThreadPoolExecutor
uses blocking queue(holding tasks before they executed)
int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
NUMBER_OF_CORES * 2, NUMBER_OF_CORES * 2 + 2, 10L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>()
);
PingThread.java
private class PingThread extends Thread {
@Override
public void run() {
long pingStartedAt = System.currentTimeMillis();
// PingRequest is custom object
PingRequest request = buildPingRequest(params);
if (!isCancelled() && !Thread.currentThread().isInterrupted()) {
// PingResponse is custom object
// Note:
// executePingRequest uses PingRequest to create a command
// which than create a runtime process to execute ping command
// using string response i am creating PingResponse
PingResponse pingResponse = PingUtils.executePingRequest(request);
if (pingResponse != null) {
pingResponse.setHopLocation(hopLocation);
// publish ping response to main GUI/handler
publishProgress(pingResponse);
} else
Logger.error(
"PingThread", "PingResponse isNull for " + request.toString()
);
}
}
}
Now if i create multiple threads say more than 500 in a loop and execute inside pool executor
Executing Threads
PingThread thread = new PingThread(params);
poolExecutor.execute(thread);
I do know that LinkedBlockingQueue
holds tasks before they executed. Each thread's process takes maximum 200 to 400ms but generally it is less than 10ms
What i am doing
for (int iteration = 1; iteration <= 50/*configurable*/; iteration++) {
for (int index = 0; index < 10/*configurable*/; index++) {
PingThread thread = new PingThread(someParams);
poolExecutor.execute(thread);
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Logger.error(false, e);
}
}
50 iterations will take about 25 seconds, here i only have up-to 40 ping responses rest consider as loss due to time out. If i increase iterations loss increases too (exponentially due to increase in no of threads)
Observation:
I am running this application on Galaxy S6 which has 8 cores, application pool size is 16 and maximum pool size is 16 + 2, i do know that processor runs only one thread at a time, it shares a quantum time for parallel processing.
By observing ThreadPoolExecutor
on timely basis, i see many tasks in queue, after timeout there are still many threads present in queue due to LinkedBlockingQueue
If i decrease no of threads it works fine but if increase it creates problem
Problem:
ConcurrentLinkedQueue
but it uses Producer/consumer model, somehow ThreadPoolExecutor
(i think it is) uses this model too.LinkedBlockingQueue
holds tasks before they executed (threads are idle or in queue), how to overcome this?Thread.MAX_PRIORITY
for latter iterations does't solve the problem (later iteration's thread are in queue)corePoolSize
like in How to get the ThreadPoolExecutor to increase threads to max before queueing? is not working in my case.During testing Memory and Processor usage are with in a limit.
Detail answer/help is required.
Edit
When application goes into background there is no loss and user CPU usage drops to 0-2% while on focus app took 4-6% of cpu usage. Is it due to UI and other ralted stuff, i tried to remove all unnecessary code also i did change PingThread
to PingTask
PingTask implements Runnable {/*....*/}
Note: I created separate java based application using same code and it works fine on desktop, so can we say it's android OS specific issue?
I am not sure if this is what causes all the problems, but you are creating a lot of unnecessary threads.
You shoud replace
private class PingThread extends Thread {
with :
private class PingThread implements Runnable {
or (using a more adequate name) :
private class PingTask implements Runnable {
i.e. the tasks submited to Executor
s are not supposed to be thread themselves. It works, because a Thread
implements Runnable
, but you are wasting it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With