简体   繁体   English

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

[英]How to run X tasks on Y threads in Java?

I want to meassure an average time of executing a task on 5 threads doing 100 tasks. 我想确保在执行100个任务的5个线程上执行任务的平均时间。

For time meassuring purposes I use nanoTime() 为了节省时间,我使用nanoTime()

The task is calling one specific method, let's call it foo(); 任务是调用一个特定的方法,让我们称之为foo(); I don't create any additional classes. 我不创建任何其他类。

In my code I create a task: 在我的代码中,我创建了一个任务:

Runnable thExecute = new Runnable(){
  @Override
  public void run(){
    foo();
  }
};

And then I create a thread: 然后我创建一个线程:

Thread th = new Thread(thExecute);
long start = System.nanoTime();
th.run();
long stop = System.nanoTime();

This would be great if I had the same number of tasks as threads. 如果我有与线程相同数量的任务,这将是很好的。 I tried to create arrays of threads and tasks: 我试图创建线程和任务的数组:

Runnable[] thExecutes = new Runnable[100];
Thread[] ths = new Thread[5];

But now I don't know what to do next. 但现在我不知道接下来该做什么。 I know they should be queued somehow and probably I should use Executor class. 我知道他们应该以某种方式排队,可能我应该使用Executor类。 I use Java 6. 我使用Java 6。

Edit: At first I didn't mean what I wrote. 编辑:起初我并不是说我写的东西。 Now I know I want average time + highest time. 现在我知道我想要平均时间+最长时间。

First thing to note: you should not expect precise results, if you measure performance by yourself. 首先要注意的是:如果您自己测量性能,则不应该期望精确的结果。 There are tools that do it for you, providing much more reliable results. 有一些工具可以帮到您,提供更可靠的结果。

If you want to do it by yourself, use ExecutorService: 如果您想自己动手,请使用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;

And again: since you are measuring nanoseconds, I strongly encourage you to avoid manual measurements, because there are many factors that will spoil the results: no warmup, setup expenses, etc. 再说一遍:由于你测量纳秒,我强烈建议你避免手动测量,因为有许多因素会破坏结果:没有预热,设置费用等。

Update : to measure execution time of every task, you can submit Callable<Long> instead of Runnable 更新 :要测量每个任务的执行时间,您可以提交Callable<Long>而不是Runnable

public long call() {
    long startTs = System.nanoTime();
    // do the task
    return System.nanoTime() - startTs;
}

Now Future will return the execution time, you can print it or gather in a list: 现在Future将返回执行时间,您可以打印它或收集列表:

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

You can use an Executor : 您可以使用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();

It will create an executor with a fix size of 5 threads then push 100 task to teh executor. 它将创建一个具有5个线程的修复大小的执行程序,然后将100个任务推送到执行程序。 The executor will dispatch the task on each thread. 执行程序将在每个线程上分派任务。

I always like to use ThreadPoolExecutor 我总是喜欢使用ThreadPoolExecutor

ThreadPoolExecutor would be more effective if you have customized many or all of below parameters preferably : BlockingQueu e Size (control unbounded queue size) , ThreadFactory for custom thread life cycle management & RejectedExecutionHandler to handle rejected tasks . 如果您已经自定义了以下许多或所有参数,则ThreadPoolExecutor会更有效: BlockingQueu e Size(控制无限制队列大小), ThreadFactory用于自定义线程生命周期管理和RejectedExecutionHandler来处理被拒绝的任务。

ThreadPoolExecutor(int corePoolSize, 
               int maximumPoolSize, 
               long keepAliveTime, 
               TimeUnit unit, 
               BlockingQueue<Runnable> workQueue, 
               ThreadFactory threadFactory,
               RejectedExecutionHandler handler)

Sample code: 示例代码:

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();
    }
 }

Your code simply does not run in a separate thread because of this 因此,您的代码不会在单独的线程中运行

th.run();

you should call start() instead of run() to achieve multi-thread functionality 你应该调用start()而不是run()来实现多线程功能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM