[英]How to run X tasks on Y threads in Java?
我想確保在執行100個任務的5個線程上執行任務的平均時間。
為了節省時間,我使用nanoTime()
任務是調用一個特定的方法,讓我們稱之為foo();
我不創建任何其他類。
在我的代碼中,我創建了一個任務:
Runnable thExecute = new Runnable(){
@Override
public void run(){
foo();
}
};
然后我創建一個線程:
Thread th = new Thread(thExecute);
long start = System.nanoTime();
th.run();
long stop = System.nanoTime();
如果我有與線程相同數量的任務,這將是很好的。 我試圖創建線程和任務的數組:
Runnable[] thExecutes = new Runnable[100];
Thread[] ths = new Thread[5];
但現在我不知道接下來該做什么。 我知道他們應該以某種方式排隊,可能我應該使用Executor
類。 我使用Java 6。
編輯:起初我並不是說我寫的東西。 現在我知道我想要平均時間+最長時間。
首先要注意的是:如果您自己測量性能,則不應該期望精確的結果。 有一些工具可以幫到您,提供更可靠的結果。
如果您想自己動手,請使用ExecutorService:
ExecutorService service = Executors.newFixedThreadPool(5);
long startTs = System.nanoTime();
List<Future> futures = new ArrayList<>();
for (Runnable r : runnables) {
futures.add(service.submit(r));
}
for (Future f : futures) {
f.get();
}
long durationNs = System.nanoTime() - startTs;
再說一遍:由於你測量納秒,我強烈建議你避免手動測量,因為有許多因素會破壞結果:沒有預熱,設置費用等。
更新 :要測量每個任務的執行時間,您可以提交Callable<Long>
而不是Runnable
public long call() {
long startTs = System.nanoTime();
// do the task
return System.nanoTime() - startTs;
}
現在Future將返回執行時間,您可以打印它或收集列表:
for (Future<Long> f : futures) {
long spentTime = f.get();
}
您可以使用Executor :
ExecutorService executorService = Executors.newFixedThreadPool(5);
long start = System.nanoTime();
for (int i = 0; i < 100; i++) {
executorService.submit(new Runnable() {
@Override
public void run() {
foo();
}
});
}
try {
// set whatever timeout value you want (must be > than the execution time)
executorService.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
long stop = System.nanoTime();
它將創建一個具有5個線程的修復大小的執行程序,然后將100個任務推送到執行程序。 執行程序將在每個線程上分派任務。
我總是喜歡使用ThreadPoolExecutor
如果您已經自定義了以下許多或所有參數,則ThreadPoolExecutor會更有效: BlockingQueu
e Size(控制無限制隊列大小), ThreadFactory
用於自定義線程生命周期管理和RejectedExecutionHandler
來處理被拒絕的任務。
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
示例代碼:
import java.util.concurrent.*;
import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy;
class SimpleThreadFactory implements ThreadFactory {
String name;
static int threadNo = 0;
public SimpleThreadFactory (String name){
this.name = name;
}
public Thread newThread(Runnable r) {
++threadNo;
System.out.println("thread no:"+threadNo);
return new Thread(r,name+":"+threadNo );
}
public static void main(String args[]){
SimpleThreadFactory factory = new SimpleThreadFactory("Factory Thread");
final ThreadPoolExecutor executor = new ThreadPoolExecutor(5,20,10,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(10),factory,new ThreadPoolExecutor.DiscardPolicy());
for ( int i=0; i < 1000; i++){
executor.submit(new Runnable(){
public void run(){
// Add t1 here
System.out.println("Thread Name in Runnable:"+Thread.currentThread().getName()+ " of "+ executor.getPoolSize() );
// print System.currentTimeMillies - t1 here
}
});
}
executor.shutdown();
}
}
因此,您的代碼不會在單獨的線程中運行
th.run();
你應該調用start()
而不是run()
來實現多線程功能
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.