Har*_*shi 13 java multithreading android blockingqueue threadpoolexecutor
我正在开发应用程序(Matt的traceroute windows版本http://winmtr.net/),它创建多个线程,每个线程都有自己的进程(执行ping命令).ThreadPoolExecutor一段时间后关闭所有线程(例如10秒)
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>()
);
Run Code Online (Sandbox Code Playgroud)
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()
);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我创建多个线程在循环中说超过500并在池执行器内执行
执行线程
PingThread thread = new PingThread(params);
poolExecutor.execute(thread);
Run Code Online (Sandbox Code Playgroud)
我知道LinkedBlockingQueue在执行任务之前保留任务.每个线程的进程最多需要200到400毫秒,但通常小于10毫秒
我在做什么
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);
}
}
Run Code Online (Sandbox Code Playgroud)
50次迭代将需要大约25秒,在这里我只有最多40个ping响应,其余被视为因超时而丢失.如果我增加迭代损失也会增加(由于没有线程增加而呈指数增长)
观察:
我在Galaxy S6上运行这个应用程序,它有8个内核,应用程序池大小为16,最大池大小为16 + 2,我知道处理器一次只运行一个线程,它共享一个量子时间进行并行处理.
通过ThreadPoolExecutor及时观察,我看到队列中有很多任务,超时后队列中仍然存在很多线程LinkedBlockingQueue
如果我减少没有线程它工作正常,但如果增加它会产生问题
问题:
ConcurrentLinkedQueue但它使用生产者/消费者模型,不知何故ThreadPoolExecutor(我认为它)也使用这个模型.LinkedBlockingQueue 在执行任务之前保存任务(线程空闲或在队列中),如何克服这个问题?Thread.MAX_PRIORITY后面的迭代不能解决问题(后来的迭代的线程在队列中)corePoolSize像如何让ThreadPoolExecutor的增加线程最大排队过吗?在我的情况下不起作用.在测试期间,内存和处理器的使用受到限制.
详细答案/帮助是必需的.
编辑
当应用程序进入后台时,没有丢失,用户CPU使用率下降到0-2%,而焦点应用程序占用了4-6%的CPU使用率.是由于UI和其他ralted东西,我试图删除所有不必要的代码,我也改变PingThread了PingTask
PingTask implements Runnable {/*....*/}
注意: 我使用相同的代码创建了单独的基于java的应用程序,它在桌面上工作正常,所以我们可以说它是Android操作系统特定的问题吗?
我不确定这是否是导致所有问题的原因,但是你创造了许多不必要的线程.
你应该替换
private class PingThread extends Thread {
Run Code Online (Sandbox Code Playgroud)
用:
private class PingThread implements Runnable {
Run Code Online (Sandbox Code Playgroud)
或(使用更充分的名称):
private class PingTask implements Runnable {
Run Code Online (Sandbox Code Playgroud)
即提交给Executors 的任务不应该是自己的线程.它起作用,因为它是一种Thread工具Runnable,但你却在浪费它.
使用相同的代码创建并观察独立的java应用程序(日志)后,我了解到以下内容:
LinkedBlockingQueue在任务执行之前保存任务,因此如果队列很长,队列中后面的线程将不得不等待更多时间。corePoolSize并且maxPoolSize正在做同样的事情,他们在队列中添加了线程对于 50 次迭代和 10 个内部创建 500 个线程,现在我做了两件事:
Thread.sleep(millis)一些计算时间。Math.ceil((double) 10 / 3) = 3,因此PingUtils.executePingRequest(pingRequest)每个线程有 3 个连续线程3 * 3 = 9,即保留 1 个线程,因此我们将为最后一个请求创建一个单独的线程。对于每次迭代,我现在创建 4 个线程,而不是创建 10 个线程。| 归档时间: |
|
| 查看次数: |
1699 次 |
| 最近记录: |