【发布时间】:2011-02-15 17:09:27
【问题描述】:
首先,再次感谢所有已经回答我问题的人。我不是一个很有经验的程序员,这是我第一次接触多线程。
我得到了一个与我的问题非常相似的示例。我希望它可以减轻我们在这里的情况。
public class ThreadMeasuring {
private static final int TASK_TIME = 1; //microseconds
private static class Batch implements Runnable {
CountDownLatch countDown;
public Batch(CountDownLatch countDown) {
this.countDown = countDown;
}
@Override
public void run() {
long t0 =System.nanoTime();
long t = 0;
while(t<TASK_TIME*1e6){ t = System.nanoTime() - t0; }
if(countDown!=null) countDown.countDown();
}
}
public static void main(String[] args) {
ThreadFactory threadFactory = new ThreadFactory() {
int counter = 1;
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "Executor thread " + (counter++));
return t;
}
};
// the total duty to be divided in tasks is fixed (problem dependent).
// Increase ntasks will mean decrease the task time proportionally.
// 4 Is an arbitrary example.
// This tasks will be executed thousands of times, inside a loop alternating
// with serial processing that needs their result and prepare the next ones.
int ntasks = 4;
int nthreads = 2;
int ncores = Runtime.getRuntime().availableProcessors();
if (nthreads<ncores) ncores = nthreads;
Batch serial = new Batch(null);
long serialTime = System.nanoTime();
serial.run();
serialTime = System.nanoTime() - serialTime;
ExecutorService executor = Executors.newFixedThreadPool( nthreads, threadFactory );
CountDownLatch countDown = new CountDownLatch(ntasks);
ArrayList<Batch> batches = new ArrayList<Batch>();
for (int i = 0; i < ntasks; i++) {
batches.add(new Batch(countDown));
}
long start = System.nanoTime();
for (Batch r : batches){
executor.execute(r);
}
// wait for all threads to finish their task
try {
countDown.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long tmeasured = (System.nanoTime() - start);
System.out.println("Task time= " + TASK_TIME + " ms");
System.out.println("Number of tasks= " + ntasks);
System.out.println("Number of threads= " + nthreads);
System.out.println("Number of cores= " + ncores);
System.out.println("Measured time= " + tmeasured);
System.out.println("Theoretical serial time= " + TASK_TIME*1000000*ntasks);
System.out.println("Theoretical parallel time= " + (TASK_TIME*1000000*ntasks)/ncores);
System.out.println("Speedup= " + (serialTime*ntasks)/(double)tmeasured);
executor.shutdown();
}
}
每个批次不进行计算,而是等待给定的时间。程序计算 加速,理论上它总是 2,但如果“TASK_TIME”很小,则可以得到小于 1(实际上是减速)。
我的计算需要 1 毫秒,通常更快。在 1 毫秒内,我发现大约 30% 的加速,但在实践中,使用我的程序,我注意到 减速。
这段代码的结构和我的程序很相似,如果你能帮助我优化线程处理,我将不胜感激。
亲切的问候。
下面,原来的问题:
嗨。
我想在我的程序中使用多线程,因为我相信它可以大大提高它的效率。它的大部分运行时间是由于独立计算。
我的程序有数千个独立的计算(要解决几个线性系统),但它们只是由几十个左右的小团体同时发生。这些组中的每一个都需要几毫秒才能运行。在其中一组计算之后,程序必须按顺序运行一段时间,然后我必须再次求解线性系统。
实际上,可以将这些要求解的独立线性系统视为在一个循环中,该循环迭代数千次,与依赖于先前结果的顺序计算交替进行。我加快程序速度的想法是在并行线程中计算这些独立计算,方法是将每个组划分为(我可用的处理器数量)批次的独立计算。所以,原则上根本不用排队。
我尝试使用 FixedThreadPool 和 CachedThreadPool,它甚至比串行处理还要慢。每次我需要解决批次时,似乎都需要花费太多时间来创建新的 Treads。
有没有更好的方法来处理这个问题?我使用的这些池似乎适用于每个线程需要更多时间而不是数千个较小线程的情况......
谢谢! 最好的问候!
【问题讨论】:
-
可以贴一些代码吗?如果您使用固定线程池,则它不会一遍又一遍地创建线程(它们被重用)。
-
你在什么平台上运行这个?多核服务器与 5 年前的黑莓之间的巨大差异。
-
@ursoouindio 我提出了一个带有阻塞队列的生产者/消费者模式,请查看我的答案以获取更多详细信息。
-
@Jeff:我必须创建一个类似的示例,因为我的代码依赖于几个类。我相信线程创建问题是由于并行和顺序部分的交替。实际上,并行部分只是程序代码的一小部分。
-
@MusiGenesis,我在两台机器上使用 Ubuntu Linux 10.04:Core 2 Duo T7250 和 Core 2 Quad Q6600。
标签: java multithreading threadpool