2014-07-01 85 views
0

下面是我的代码。我正在通过线程填充大小为3500000的列表。首先我通过一个线程填充列表。此线程将返回包含3500000项的字符串列表。多线程执行时间最小化

此过程需要5秒钟才能执行。

然后,我创建了另一个线程,并将整个任务分为两部分,并将它们分配给线程。

第一个线程将填充1900000项目的字符串列表,第二个线程将返回(3500000-1900000 = 1600000)项目。这两个过程并行运行。所以,应该花更少的时间。 但是,对于这种情况,总计算时间也是5秒。

请有人帮我找出我做错了什么?

我非常需要最小化执行时间。我怎样才能最小化时间?

package callablefutures; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 
import java.util.Calendar; 
import java.util.concurrent.TimeUnit; 
import java.util.Date; 

public class CallableFutures { 

    private static final int NTHREDS = 10; 
    public static void main(String[] args) { 

    ExecutorService executor = Executors.newFixedThreadPool(NTHREDS); 
    List<Future<List<String>>> list = new ArrayList<Future<List<String>>>(); 


    List<List<String>> lst=new ArrayList(); 
    List<String> list1=new ArrayList(); 
    List<String> list2=new ArrayList(); 


    Runtime rt = Runtime.getRuntime(); 
    long prevFree = rt.freeMemory(); 
    long startTime=System.currentTimeMillis(); 


     Callable<List<String>> worker = new MyCallable(list1,0,1900000); 
     Future<List<String>> submit = executor.submit(worker); 
     list.add(submit); 

     Callable<List<String>> worker1 = new MyCallable(list2,1900000,3500000); 
     Future<List<String>> submit1 = executor.submit(worker1); 
     list.add(submit1); 

    long sum = 0; 
    System.out.println(list.size()); 

    for (Future<List<String>> future : list) { 
     try { 
      lst.add(future.get()); 
     } catch (InterruptedException e) { 
     e.printStackTrace(); 
     } catch (ExecutionException e) { 
     e.printStackTrace(); 
     } 
    } 
    executor.shutdown(); 
    long endTime=System.currentTimeMillis(); 
    System.out.println("Total Time Taken: " + (endTime-startTime)/1000%60 +" Seconds"); 
    System.out.println("Total Memory Taken (MB): " + ((prevFree-rt.freeMemory())/1024)/1024); 
    } 
} 



package callablefutures; 
import java.util.concurrent.Callable; 
import java.util.List; 
import java.util.ArrayList; 

public class MyCallable implements Callable<List<String>>{ 
    public List<String> StrList=new ArrayList(); 
    public int sIndex,eIndex; 
    public MyCallable(List<String> oList,int si,int ei) 
    { 
     this.StrList=oList; 
     this.sIndex=si; 
     this.eIndex=ei; 
    } 
    @Override 
    public List<String> call() throws Exception { 

    for (int i = this.sIndex; i < this.eIndex; i++) { 
     this.StrList.add("ID "+i); 
    } 
    return this.StrList; 
    //return this.StrList; 
    } 

} 
+1

你的基准测试大多只是分配内存 - 很可能它不会很好地扩展。你可以尝试'新ArrayList(1900000)'预先分配至少列表,但我怀疑这会有很大帮助。在现代JVM中运行的基准测试代码并不容易,而且你做错了:http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – Chris

回答

0

你正在创建大约128 MB的数据,这将是比你的L3缓存更大,所以你将力推数据到主内存,这通常是很容易与一个线程饱和。如果您希望线程同时运行,您希望每个线程都被限制为256 KB(因为它们每个都有自己的L2高速缓存,假设它们运行在不同的核心上),或者如果在同一个核心上,每个都需要128 KB。

+0

你能否给我提供一个java代码示例,这样我就可以真正看到应用多线程,执行时间可以减少......理论上我知道这是可能的,但实际上我无法生成它。请帮助我!谢谢。 – dpkkry

+0

更改您的程序以执行CPU密集型操作,而不是内存或IO无效操作,例如通过递归计算斐波那契数。 (显然,迭代速度要快得多,但作为例子) –