【发布时间】:2019-09-16 23:32:35
【问题描述】:
我正在尝试实现的任务是使用多个线程在设定的时间间隔内查找 Collatz 数字序列,并查看与一个线程相比获得了多少改进。
但是,无论我选择 2 个线程,一个线程总是更快(编辑。2 个线程更快,但不会快很多,而 4 个线程比 1 个线程慢,我不知道为什么。(我什至可以说线程越多越慢)。我希望有人能解释一下。也许我做错了什么。
以下是我目前编写的代码。我正在使用 ThreadPoolExecutor 来执行任务(一个任务 = 一个 Collatz 序列,用于间隔中的一个数字)。
Collatz 类:
public class ParallelCollatz implements Runnable {
private long result;
private long inputNum;
public long getResult() {
return result;
}
public void setResult(long result) {
this.result = result;
}
public long getInputNum() {
return inputNum;
}
public void setInputNum(long inputNum) {
this.inputNum = inputNum;
}
public void run() {
//System.out.println("number:" + inputNum);
//System.out.println("Thread:" + Thread.currentThread().getId());
//int j=0;
//if(Thread.currentThread().getId()==11) {
// ++j;
// System.out.println(j);
//}
long result = 1;
//main recursive computation
while (inputNum > 1) {
if (inputNum % 2 == 0) {
inputNum = inputNum / 2;
} else {
inputNum = inputNum * 3 + 1;
}
++result;
}
// try {
//Thread.sleep(10);
//} catch (InterruptedException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
//}
this.result=result;
return;
}
}
以及我运行线程的主类(是的,现在我创建了两个具有相同数字的列表,因为在使用一个线程运行后初始值丢失):
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newFixedThreadPool(1);
ThreadPoolExecutor executor2 = (ThreadPoolExecutor)Executors.newFixedThreadPool(4);
List<ParallelCollatz> tasks = new ArrayList<ParallelCollatz>();
for(int i=1; i<=1000000; i++) {
ParallelCollatz task = new ParallelCollatz();
task.setInputNum((long)(i+1000000));
tasks.add(task);
}
long startTime = System.nanoTime();
for(int i=0; i<1000000; i++) {
executor.execute(tasks.get(i));
}
executor.shutdown();
boolean tempFirst=false;
try {
tempFirst =executor.awaitTermination(5, TimeUnit.HOURS);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("tempFirst " + tempFirst);
long endTime = System.nanoTime();
long durationInNano = endTime - startTime;
long durationInMillis = TimeUnit.NANOSECONDS.toMillis(durationInNano); //Total execution time in nano seconds
System.out.println("laikas " +durationInMillis);
List<ParallelCollatz> tasks2 = new ArrayList<ParallelCollatz>();
for(int i=1; i<=1000000; i++) {
ParallelCollatz task = new ParallelCollatz();
task.setInputNum((long)(i+1000000));
tasks2.add(task);
}
long startTime2 = System.nanoTime();
for(int i=0; i<1000000; i++) {
executor2.execute(tasks2.get(i));
}
executor2.shutdown();
boolean temp =false;
try {
temp=executor2.awaitTermination(5, TimeUnit.HOURS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("temp "+ temp);
long endTime2 = System.nanoTime();
long durationInNano2 = endTime2 - startTime2;
long durationInMillis2 = TimeUnit.NANOSECONDS.toMillis(durationInNano2); //Total execution time in nano seconds
System.out.println("laikas2 " +durationInMillis2);
例如使用一个线程运行它在 3280 毫秒内完成。用两个线程运行 3437 毫秒。我是否应该考虑另一种并发结构来计算每个元素?
编辑 澄清。我不是在尝试并行化单个序列,而是在每个数字都有其序列时的数字间隔。(与其他数字无关)
EDIT2
今天我在一台具有 6 个内核和 12 个逻辑处理器的良好 PC 上运行该程序,但问题仍然存在。有谁知道问题可能出在哪里?我还更新了我的代码。由于某种原因,4 个线程比 2 个线程做得更差。(甚至比 1 个线程更差)。我也应用了答案中给出的内容,但没有改变。
另一个编辑 我注意到,如果我在我的 ParallelCollatz 方法中放置一个 Thread.sleep(1) ,那么性能会随着线程数的增加而逐渐增加。也许这个细节告诉某人出了什么问题?但是,如果没有 Thread.Sleep(1),无论我给出多少任务,2 个线程执行速度最快,1 个线程排在第二位,其他线程挂起的毫秒数相似,但都比 1 个和 2 个线程慢。
新编辑 我还尝试在 Runnable 类的 run() 方法中放置更多任务(用于计算不是 1 而是 10 或 100 个 Collatz 序列的循环),以便线程本身可以做更多的工作。不幸的是,这也没有帮助。 也许我错误地启动了任务?有人有什么想法吗?
编辑 因此,在向 run 方法添加更多任务之后,似乎可以稍微修复它,但对于更多线程,问题仍然是 8+。我仍然想知道这是因为创建和运行线程比执行任务需要更多时间吗?还是我应该用这个问题创建一个新帖子?
【问题讨论】:
-
我正在计算一个序列,比如说 10000 个数字。每个数字都有我试图并行执行的序列,这些序列是不相关的。最终目标是找到最长的,但现在我只是尝试在单独的线程中运行这些序列。
-
您使用的是 1 个核心吗?
-
我正在使用一台配备英特尔酷睿 i5-4202Y CPU 的笔记本电脑(不是很好,但它有 2 个内核和 4 个逻辑处理器)。
-
尝试最大化测试,所以它需要 30 秒而不是 3 秒来完成,并检查它是否使用 2 个逻辑处理器来完成这项工作。如果没有,则没有任何优化,cpu 轮次变化可能会延迟你
-
这只是理论,似乎是多任务,而不是多线程
标签: java multithreading threadpool executorservice collatz