【问题标题】:Read from arraylist using two thread concurrently同时使用两个线程从arraylist读取
【发布时间】:2016-07-17 13:12:23
【问题描述】:

有一个 ArrayList 有 100 万个元素,我们使用两个线程从这个 ArrayList 中读取。第一个线程将读取列表的前半部分,第二个线程将读取列表的后半部分,我使用两个线程来实现这一点,但我看不出使用一个线程和两个线程之间的性能有何差异。

我已经编写了下面的程序来实现这一点,但我不确定这是否是实现和实现这一目标的正确方法。

谁能检查我的代码是否正确或如何修复多线程?

import java.util.ArrayList;
import java.util.List;

public class ThreadTask {

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub

        List<Integer> list = new ArrayList<>();
        for(int i = 0; i <=1000000; i++){
            list.add(i);
        }

        Thread t1 = new Thread(new PrintList(list));
        Thread t2 = new Thread(new PrintList(list));
        t1.setName("thread1");
        t2.setName("thread2");
       long starttime = System.currentTimeMillis();
       System.out.println(starttime);
       t1.start();
       t2.start();
       t1.join(); 
       t2.join();
       long endtime = System.currentTimeMillis();
       System.out.println(endtime);
       System.out.println("Total time "+(endtime - starttime));     
    }


}

class PrintList implements Runnable{

    private List list = new ArrayList();
    public PrintList(List list){
        this.list = list;
    }


    @Override
    public void run() {
     if(Thread.currentThread().getName() != null && Thread.currentThread().getName().equalsIgnoreCase("thread1")){

         for(int i = 0; i< list.size()/2;i++){
            // System.out.println("Thread 1 "+list.get(i));
         }
     }else if(Thread.currentThread().getName() != null && Thread.currentThread().getName().equalsIgnoreCase("thread2")){

         for(int i = list.size()/2; i<list.size(); i++){
             //System.out.println("Thread 2 "+list.get(i));
         }
     }  
    }   
}

另外,如果有人可以帮助我了解我们如何实现它以使其通用,以便使用更多然后线程。

【问题讨论】:

  • 尼特:您的列表有 1,000,001 个元素。
  • 在屏幕上显示数字的大部分工作是将文本渲染为像素。您的代码不会以任何方式改变这一点。
  • @PeterLawrey - 我想我没有以正确的方式提出问题。我根本不专注于打印,我在我的代码中评论了那部分,我想要实现的是使用超过 1 个线程读取 1 个大型数组列表,其中每个线程将同时读取一段列表,如果你可以建议一些实现这一目标的方法。
  • 你的意思是list.parallelStream().forEach(i -&gt; doSomething(i));?这将使用您机器上的所有 CPU 来处理列表中的元素。更简单的是Stream.range(0, 1000000).parallel().forEach(i -&gt; ...)

标签: java multithreading


【解决方案1】:

System.out.println 是在内部同步的(这样您就不会在多个线程打印的消息之间产生混淆),因此实际上一次只有一个线程在打印。

基本上,它的行为就像一个单线程。

【讨论】:

  • 但是,它有资源争用,所以使用两个线程可能比一个线程慢。
【解决方案2】:

即使实际上 System.out 是同步的,您仍然不希望手动初始化从 ArrayList 读取的线程。另外,我怀疑您的最终目标是 System.out。您应该使用更高的抽象。这种抽象可以很容易地通过 Java8 Stream API 或 ExecutorServices 呈现。

这是一个使用 Java 8 api 的并行示例。

要打印的数组列表;

toPrint.parallelstream().forEach(DoSometing);

这将在并行线程中工作。

如果您使用 ExecutorService,您可以对 Arraylist 进行切片并将每个切片传递给 Callable,以便在单独的线程中为您执行工作。

class Task implements Callable {
  List sublist;
  public Task(List sublist) {
       this.sublist = sublist;
  }

  public void call() {
     // do something
  }
}

ArrayList listToSlice;
List<List> slicedList;
ExecutorService executor = Executors.newFixedThreadPool(2);
for (List sublist:slicedList) {
   Future<Integer> future = executor.submit(new Task(sublist));
......
.......s on
}

【讨论】:

    猜你喜欢
    • 2013-10-20
    • 1970-01-01
    • 2021-09-10
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 2014-06-28
    • 2014-07-15
    相关资源
    最近更新 更多