[英]Java (Android) multi-threading process
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). 我正在开发应用程序( Matt的traceroute windows版本http://winmtr.net/ ),它创建多个线程,每个线程都有自己的进程(执行ping命令)。 ThreadPoolExecutor
shutdown all threads after some time( eg10 seconds) ThreadPoolExecutor
在一段时间后关闭所有线程(例如10秒)
ThreadPoolExecutor
uses blocking queue(holding tasks before they executed) 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 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 现在,如果我创建多个线程在循环中说超过500并在池执行器内执行
Executing Threads 执行线程
PingThread thread = new PingThread(params);
poolExecutor.execute(thread);
I do know that LinkedBlockingQueue
holds tasks before they executed. 我知道LinkedBlockingQueue
在执行之前保存任务。 Each thread's process takes maximum 200 to 400ms but generally it is less than 10ms 每个线程的进程最多需要200到400毫秒,但通常小于10毫秒
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. 50次迭代将需要大约25秒,在这里我只有最多40个ping响应,其余被视为因超时而丢失。 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. 我在Galaxy S6上运行这个应用程序,它有8个内核,应用程序池大小为16,最大池大小为16 + 2,我知道处理器一次只运行一个线程,它共享一个量子时间进行并行处理。
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
通过及时观察ThreadPoolExecutor
,我看到队列中有很多任务,在超时后,由于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. 我应该使用ConcurrentLinkedQueue
但它使用生产者/消费者模型,不知何故ThreadPoolExecutor
(我认为它)也使用这个模型。 LinkedBlockingQueue
holds tasks before they executed (threads are idle or in queue), how to overcome this? LinkedBlockingQueue
在执行任务之前保存任务(线程空闲或在队列中),如何克服这个问题? Thread.MAX_PRIORITY
for latter iterations does't solve the problem (later iteration's thread are in queue) 通过为后面的迭代设置Thread.MAX_PRIORITY
不能解决问题(后来的迭代的线程在队列中) corePoolSize
like in How to get the ThreadPoolExecutor to increase threads to max before queueing? 更改corePoolSize
就像如何让ThreadPoolExecutor在排队前将线程增加到最大值? 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. 当应用程序进入后台时,没有丢失,用户CPU使用率下降到0-2%,而焦点应用程序占用了4-6%的CPU使用率。 Is it due to UI and other ralted stuff, i tried to remove all unnecessary code also i did change PingThread
to PingTask
是由于UI和其他ralted东西,我试图删除所有不必要的代码,我也改变PingThread
到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? 注意:我使用相同的代码创建了单独的基于java的应用程序,它在桌面上工作正常,所以我们可以说它是Android操作系统特定的问题吗?
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 {
ie the tasks submited to Executor
s are not supposed to be thread themselves. 即提交给Executor
的任务不应该是自己的线程。 It works, because a Thread
implements Runnable
, but you are wasting it. 它有效,因为一个Thread
实现了Runnable
,但是你在浪费它。
Threads create a new unique object, while runnable allows all the threads to share one object. 线程创建一个新的唯一对象,而runnable允许所有线程共享一个对象。 As such, you should not extend Thread when trying to multithread, instead use Runnable: 因此,在尝试多线程时不应扩展Thread,而是使用Runnable:
class RunnableDemo implements Runnable {
private Thread thread;
String threadName="My thread";
public void run() {
//do your code from here 'logic'
System.out.println("Threading is Running");
try {
for(int i = 4; i > 0; i--) {
System.out.println("Thread: "+threadName +" "+ i);
// Let the thread sleep for a while.
Thread.sleep(50); //sleep your content for xx miliseconds
}
} catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
//finish your work here
}
public void start () {
System.out.println("Starting " + threadName );
if (thread == null) {
thread = new Thread (this);
thread.start (); //This will call your run methods of Runnable
}
}
}
//test your thread from here
public class TestThread {
public static void main(String args[]) {
RunnableDemo R1 = new RunnableDemo( "Thread-1");
R1.start();
RunnableDemo R2 = new RunnableDemo( "Thread-2");
R2.start();
}
}
After creating and observing a independent java application (logs) using same code, I came to know the followings: 在使用相同的代码创建和观察独立的Java应用程序(日志)之后,我开始了解以下内容:
LinkedBlockingQueue
holds tasks before they executed, so if we have a long queue later threads in queue will have to wait more. LinkedBlockingQueue
在执行任务之前保存任务,因此如果我们有一个长队列,队列中的线程将不得不等待更多。 corePoolSize
and maxPoolSize
is doing the same, they added threads in queue 增加/动态corePoolSize
和maxPoolSize
也是这样,他们在队列中添加了线程 For 50 iterations and 10 inner creates 500 threads now i did two things: 对于50次迭代和10次内部创建500个线程,我现在做了两件事:
Thread.sleep(millis)
time with some calculation involves. 通过一些计算涉及增加Thread.sleep(millis)
时间。 Math.ceil((double) 10 / 3) = 3
so we have 3 sequential PingUtils.executePingRequest(pingRequest)
for each thread ie 3 * 3 = 9
remains 1 so we will create a separate thread for last request. 我正在创建10个线程,现在Math.ceil((double) 10 / 3) = 3
PingUtils.executePingRequest(pingRequest)
Math.ceil((double) 10 / 3) = 3
所以我们为每个线程有3个连续的PingUtils.executePingRequest(pingRequest)
,即3 * 3 = 9
仍为1所以我们将为last创建一个单独的线程请求。 For each iteration instead of creating 10 threads now i am creating 4 threads. 对于每次迭代而不是现在创建10个线程我创建了4个线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.