如何在 Java 的 Y 线程上 运行 X 任务?

How to run X tasks on Y threads in Java?

我想测量在执行 100 个任务的 5 个线程上执行任务的平均时间。

出于时间测量的目的,我使用 nanoTime()

任务正在调用一个特定的方法,我们称它为foo(); 我不创建任何额外的 classes。

在我的代码中我创建了一个任务:

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 class。我用 Java 6.

编辑: 起初我不是故意的。现在我知道我想要平均时间 + 最高时间。

您可以使用 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 个任务推送给该执行器。执行器会在每个线程上分派任务。

首先要注意的是:如果您自己衡量性能,则不应期望得到精确的结果。有 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;
}

现在 Future 将 return 执行时间,您可以打印它或收集在列表中:

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

我一直喜欢用ThreadPoolExecutor

ThreadPoolExecutor 如果您最好自定义了以下许多或所有参数,会更有效:BlockingQueue 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() 来实现 multi-thread 功能