Java多线程处理List数据

时间:2021-07-12 18:32:19

多线程数量的问题,一般情况下,多线程数量要等于机器CPU核数-1.

实例1:

解决问题:如何让n个线程顺序遍历含有n个元素的List集合

 

Java多线程处理List数据Java多线程处理List数据
 1 import java.util.ArrayList;
 2 import java.util.List;
 3 import org.apache.commons.lang3.ArrayUtils;
 4  
 5 public class Test_4 {
 6     /**
 7      * 多线程处理list
 8      *
 9      * @param data  数据list
10      * @param threadNum  线程数
11      */
12     public synchronized void handleList(List<String> data, int threadNum) {
13         int length = data.size();
14         int tl = length % threadNum == 0 ? length / threadNum : (length
15                 / threadNum + 1);
16  
17         for (int i = 0; i < threadNum; i++) {
18             int end = (i + 1) * tl;
19             HandleThread thread = new HandleThread("线程[" + (i + 1) + "] ",  data, i * tl, end > length ? length : end);
20             thread.start();
21         }
22     }
23  
24     class HandleThread extends Thread {
25         private String threadName;
26         private List<String> data;
27         private int start;
28         private int end;
29  
30         public HandleThread(String threadName, List<String> data, int start, int end) {
31             this.threadName = threadName;
32             this.data = data;
33             this.start = start;
34             this.end = end;
35         }
36         
37         public void run() {
38             List<String> subList = data.subList(start, end)/*.add("^&*")*/;
39             System.out.println(threadName+"处理了"+subList.size()+"条!");
40         }
41  
42     }
43  
44     public static void main(String[] args) {
45         Test_4 test = new Test_4();
46         // 准备数据
47         List<String> data = new ArrayList<String>();
48         for (int i = 0; i < 6666; i++) {
49             data.add("item" + i);
50         }
51         test.handleList(data, 5);
52         System.out.println(ArrayUtils.toString(data));
53     }
54 }
View Code

 

实例2:

List多线程并发读取读取现有的list对象

Java多线程处理List数据Java多线程处理List数据
 1 //测试读取List的线程类,大概34秒
 2 package com.thread.list;
 3  
 4 import java.util.ArrayList;
 5 import java.util.HashMap;
 6 import java.util.List;
 7 import java.util.Map;
 8  
 9 public class Main {
10     
11     public static void main(String[] args) {
12         
13         List<String> list = new ArrayList<String>();
14         Map<Long,Integer> map = new HashMap<Long,Integer>();
15 
16         for(int i = 0;i<1000;i++){
17             list.add(""+i);
18         }
19         
20         int pcount = Runtime.getRuntime().availableProcessors();        
21         long start = System.currentTimeMillis();        
22         
23         for(int i=0;i<pcount;i++){
24             
25            Thread t = new MyThread1(list,map);
26             map.put(t.getId(),Integer.valueOf(i));
27             t.start();
28             try {
29                 t.join();
30             } catch (InterruptedException e) {              
31                 e.printStackTrace();
32             }            
33            // System.out.println(list.get(i));
34         }        
35         System.out.println("----"+(System.currentTimeMillis() - start));
36     }    
37 }
38 
39 //线程类
40 package com.thread.list;
41  
42 import java.util.List;
43 import java.util.Map;
44  
45 public class MyThread1 extends Thread {
46  
47     private List<String> list;
48     private Map<Long,Integer> map;
49     
50     public MyThread1(List<String> list,Map<Long,Integer> map){
51         this.list = list;
52         this.map = map;
53     }
54     
55     @Override
56     public void run() {
57         
58         int pcount = Runtime.getRuntime().availableProcessors();
59         int i = map.get(Thread.currentThread().getId());
60         
61         for(;i<list.size();i+=pcount){
62             System.out.println(list.get(i));
63         }              
64     }    
65 }
View Code

实例3:

多线程分段处理List集合

场景:大数据List集合,需要对List集合中的数据同标准库中数据进行对比,生成新增,更新,取消数据
解决方案:

  1. List集合分段,
  2. 动态创建线程池newFixedThreadPool
  3. 将对比操作在多线程中实现
Java多线程处理List数据Java多线程处理List数据
 1 public static void main(String[] args) throws Exception {
 2 
 3         // 开始时间
 4         long start = System.currentTimeMillis();
 5         List<String> list = new ArrayList<String>();
 6 
 7         for (int i = 1; i <= 3000; i++) {
 8             list.add(i + "");
 9         }
10         // 每500条数据开启一条线程
11         int threadSize = 500;
12         // 总数据条数
13         int dataSize = list.size();
14         // 线程数
15         int threadNum = dataSize / threadSize + 1;
16         // 定义标记,过滤threadNum为整数
17         boolean special = dataSize % threadSize == 0;
18 
19         // 创建一个线程池
20         ExecutorService exec = Executors.newFixedThreadPool(threadNum);
21         // 定义一个任务集合
22         List<Callable<Integer>> tasks = new ArrayList<Callable<Integer>>();
23         Callable<Integer> task = null;
24         List<String> cutList = null;
25 
26         // 确定每条线程的数据
27         for (int i = 0; i < threadNum; i++) {
28             if (i == threadNum - 1) {
29                 if (special) {
30                     break;
31                 }
32                 cutList = list.subList(threadSize * i, dataSize);
33             } else {
34                 cutList = list.subList(threadSize * i, threadSize * (i + 1));
35             }
36             // System.out.println("第" + (i + 1) + "组:" + cutList.toString());
37             final List<String> listStr = cutList;
38             task = new Callable<Integer>() {
39 
40                 @Override
41                 public Integer call() throws Exception {
42                     System.out.println(Thread.currentThread().getName() + "线程:" + listStr);
43                     return 1;
44                 }
45             };
46             // 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
47             tasks.add(task);
48         }
49 
50         List<Future<Integer>> results = exec.invokeAll(tasks);
51 
52         for (Future<Integer> future : results) {
53             System.out.println(future.get());
54         }
55 
56         // 关闭线程池
57         exec.shutdown();
58         System.out.println("线程任务执行结束");
59         System.err.println("执行任务消耗了 :" + (System.currentTimeMillis() - start) + "毫秒");
60     }
View Code