我想写一个 Eratosthenes 的筛子,它可以使用特定数量的线程。我发现它将以下列方式工作:对于最多 17 个线程的 2 个线程。线程 1 需要 2,并开始从列表中删除 2 的倍数。Parallel Thread-2 需要 3 并且执行相同的操作。之后,Thread-1 需要 5(因为 List 中没有 4),Thread-2 需要 7,依此类推,直到它们结束。我写了以下代码:
private List<Integer> array = new ArrayList<Integer>();
private List<Integer> results = new ArrayList<Integer>();
public synchronized void run(){
while(array.size() > 0){
Integer tmp = array.get(0);
for(int i = 1; i < array.size(); i++){
if( (array.get(i).intValue() % tmp.intValue()) == 0)
array.remove(i);
}
results.add(array.get(0));
array.remove(0);
}
}
public void setArray(int x){
for(int i = 2; i < x; i++)
array.add(Integer.valueOf(i));
}
public void printArray(){
for(Integer i: results){
System.out.println(i);
}
}
此代码有效,但我在我的主类中添加了时间测量“工具”:
ThreadTask task = new ThreadTask();
task.setArray(5000);
Long beg = new Date().getTime();
for(int i = 0; i < 3;i++){
new Thread(task).start();
}
Long sleep = 1000L;
Thread.sleep(sleep);// I am sleeping main thread to wait until other Threads are done
task.printArray();
System.out.println("Time is "+(new Date().getTime()-beg-sleep));
问题是使用 2 个线程运行它比使用 1 个线程运行慢,并且 3 个线程比 2 个线程慢。谁能解释一下,为什么?
编辑:
有一件很重要的事情。我不需要尽可能快地完成它。出于一个原因,我需要它在线程上工作。我的老师想比较运行同一程序与 1、2 .. n 线程的运行时间。结果应如下图所示。
编辑2:
我已将代码重写为以下
private HashMap<Integer,Boolean> array = new HashMap<Integer,Boolean>();
private int counter = 1;
private int x;
public void run(){
while(counter < x-1){
do{
counter++;
}
while( array.get(counter));
int tmp = counter;
for(int i = tmp; i < array.size(); i+=tmp){
if( i!= tmp)
array.put(i,true);
}
try{
Thread.sleep(0L, 1);
}
catch (Exception e){}
}
}
public void setArray(int x){
this.x = x;
for(int i = 2; i < x; i++)
array.put(i, false);
}
public void printArray(){
for(int i = 2; i < array.size();i++){
if( !array.get(i))
System.out.println(i);
}
}
现在它使用 HashMap,它是这样工作的:
- 用从 2 到 n 的键和假值填充 HashMap。
- 新线程进入基于
counter
变量的 while 循环。Counter
表示当前键。 - 在乞求时增加计数器,这样新线程就不会对
counter
较早启动的线程进行操作。 - 将
counter
值放入临时变量tmp
中,这样即使另一个线程增加,我们也可以工作counter
i
通过递增(tmp
实际上是在 i 的倍数上跳跃)遍历 HashMap并将它们的值设置为true
。- 在 print 方法中,所有具有
true
值的键都会被忽略。增加时也会counter
跳过它们。
问题是它在使用更多线程时仍然工作得更慢。现在怎么了?