2

我想確定在執行100個任務的5個線程上執行任務的平均時間。如何在Java中的Y線程上運行X任務?

對於時間meassuring目的,我使用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.編輯: 起初我並不是指我寫的東西。現在我知道我想要平均時間+最高時間。

+2

查看[Executor界面](https://docs.oracle.com/jav) ase/7/docs/api/java/util/concurrent/Executor.html) – jhamon

+4

您可以使用Executors.newFixedThreadPool(5),然後提交您的100個Runnables。 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool%28int%29 – Thilo

回答

4

首先要注意的是:如果你自己測量性能,你不應該期待精確的結果。有tools爲你做,提供更可靠的結果。

如果你想自己做,用的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; 
} 

現在和未來將返回執行時間,你可以打印或聚集在一個列表:

for (Future<Long> f : futures) { 
    long spentTime = f.get(); 
} 
+0

我改變了我的問題一點。我可以把startTs和stopTs放在f.get();獲得一項任務的時間? – Kamil

+1

@Kamil那麼使用Callable代替它會更好,它會返回執行時間,請參閱更新回答 – AdamSkywalker

+0

那麼,我在哪裏使用Collable並在哪裏調用call()? – Kamil

2

您可以使用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任務執行德。執行程序將在每個線程上分派任務。

0

我總是喜歡用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(); 
    } 
} 
0

您的代碼根本不會因爲這樣一個單獨的線程運行

th.run(); 

你應該叫start()而不是run()實現多線程功能

+0

是的,有開始(),但因爲我一直在閱讀你不應該使用run()它卡在我的腦海裏,我在這裏鍵入run() – Kamil

相關問題