Java (Android) 多线程进程
我正在开发应用程序(Matt的traceroute windows版本 http://winmtr.net/),它创建多线程,每个线程都有自己的进程(执行ping命令)。 一段时间后关闭所有线程(例如10秒)ThreadPoolExecutor
ThreadPoolExecutor
使用阻塞队列(在执行任务之前保留任务)
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()
);
}
}
}
现在,如果我创建多个线程,在循环中说超过500个,并在池执行器内部执行
执行线程
PingThread thread = new PingThread(params);
poolExecutor.execute(thread);
我确实知道在执行任务之前持有任务。每个线程的进程最多需要200到400ms,但通常小于10msLinkedBlockingQueue
我在做什么
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次迭代大约需要25秒,这里我只有多达40个ping响应休息,因为超时导致损失。如果 i 增加迭代,损失也会增加(由于线程数的增加而呈指数级增长)
观察:
我在Galaxy S6上运行此应用程序,它有8个内核,应用程序池大小为16,最大池大小为16 + 2,我知道处理器一次只运行一个线程,它共享一个量子时间进行并行处理。
通过及时观察,我看到队列中有许多任务,超时后队列中仍然存在许多线程,因为ThreadPoolExecutor
LinkedBlockingQueue
如果我减少没有线程,它工作正常,但如果增加它会产生问题
问题:
- 当我使用具有双核处理器的设备时,Ping 响应减少。
- 为什么队列中存在许多线程,其中每个线程大约需要10到50ms(增加线程时间会增加300ms或更多)?
- 它应该在给定的时间内完成,为什么不呢?
- 如何克服这个问题?
- 我应该使用但它使用生产者/消费者模型,不知何故(我认为它是)也使用这个模型。
ConcurrentLinkedQueue
ThreadPoolExecutor
-
LinkedBlockingQueue
在执行任务之前保留任务(线程处于空闲状态或在队列中),如何克服这一点? - 通过设置后一次迭代并不能解决问题(后期迭代的线程在队列中)
Thread.MAX_PRIORITY
- 减少线程数可以解决问题,为什么?因为队列中没有线程较少?
- 有没有办法检查,如果队列中存在的线程娱乐它们,然后执行其他线程,而不会阻塞其他线程,但在给定的时间内。
- 增加额外的时间,如5秒不是解决方案
- 在如何让 ThreadPoolExecutor 在排队之前将线程增加到最大值?中的更改在我的案例中不起作用。
corePoolSize
在测试期间,内存和处理器使用率有限制。
需要详细的答案/帮助。
编辑
当应用程序进入后台时,没有损失,用户CPU使用率下降到0-2%,而对焦应用程序占用了4-6%的CPU使用率。是由于UI和其他拉扯的东西,我试图删除所有不必要的代码,我也确实改成了PingThread
PingTask
PingTask implements Runnable {/*....*/}
注意:我使用相同的代码创建了单独的基于java的应用程序,它在桌面上工作正常,所以我们可以说它是Android操作系统特定的问题吗?