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

相关问题