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