多线程使用的一些例子

一、例子1:    

package com.csii.test.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 使用多线程查找每个学生对应老师的名字。
 * 使用线程池执行,增加并发,增加总体执行速度。
 * 最后等全部查询完毕后,打印查询时间
 */
public class TestMultiThread {
    /**
     * n = 核心数*2 + 1
     */
    private static ExecutorService pool = Executors.newFixedThreadPool(5);

    public static void main(String[] args) {
        //findMethod1();
        findMethod2();
        pool.shutdown();
    }

    /**
     * 方法1:
     * 模拟,使用多线程,找到每个学生的老师名字,并且打印出来。
     * 使用countDownLatch
     */
    private static void findMethod1() {
        long begin = System.currentTimeMillis();

        List<String> studentList = new ArrayList<>();
        studentList.add("zhangsan");
        studentList.add("lisi");
        studentList.add("wangwu");

        try {
            CountDownLatch latch = new CountDownLatch(studentList.size());
            for(String student : studentList){
                pool.execute(() -> {
                    findTeacher(student);
                    latch.countDown();
                });
            }
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("findMethod1执行完毕,耗时:" + (System.currentTimeMillis() - begin) + "ms");
    }

    /**
     * 方法2:使用CompletableFuture来完成
     */
    private static void findMethod2() {
        long begin = System.currentTimeMillis();

        List<String> studentList = new ArrayList<>();
        studentList.add("zhangsan");
        studentList.add("lisi");
        studentList.add("wangwu");

        CompletableFuture.allOf(studentList.stream().map(s -> CompletableFuture.runAsync(() -> findTeacher(s))).toArray(CompletableFuture[]::new)).join();

        System.out.println("findMethod2执行完毕,耗时:" + (System.currentTimeMillis() - begin) + "ms");
    }

    /**
     * 模拟数据库中查找学生的操作,耗时3秒
     */
    private static void findTeacher(String studentName) {
        System.out.println("开始处理学生:" + studentName);
        //模拟查数据库...等操作,查找学生的老师
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("teacher: " + studentName + "'s teacher");
    }
}

console:

方法1执行:

开始处理学生:zhangsan
开始处理学生:wangwu
开始处理学生:lisi
teacher: lisi's teacher
teacher: wangwu's teacher
teacher: zhangsan's teacher
findMethod1执行完毕,耗时:3043ms

方法2执行:

开始处理学生:zhangsan
开始处理学生:wangwu
开始处理学生:lisi
teacher: wangwu's teacher
teacher: zhangsan's teacher
teacher: lisi's teacher
findMethod2执行完毕,耗时:3056ms

 

 

二、例子2:    

package com.csii.test.thread;


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestMultiThread2 {
    private static int minProcessCnt = 1;
    private static int poolSize = 5;
    private static ExecutorService pool = Executors.newFixedThreadPool(poolSize);

    /**
     * 1.模拟,使用多线程,找到每个学生的老师名字,并且打印出来。
     * @param args
     */
    public static void main(String[] args) {
        long begin = System.currentTimeMillis();

        List<String> studentList = new ArrayList<>();
        studentList.add("zhangsan");
        studentList.add("lisi");
        studentList.add("wangwu");

        int perCnt = studentList.size() / poolSize;             //每个线程处理的数量
        int step = Math.max(perCnt, minProcessCnt);             //每个线程处理的数量,按照step切割list
        int latchNum = (studentList.size() + step - 1) / step;  //处理次数 (和分页计算方法一样:pageCount = (totalCount + pageSize - 1)/pageSize )
        CountDownLatch latch = new CountDownLatch(latchNum);

        //切割studentList,分批查询
        try {
            for (int i = 0, start = 0; i < latchNum; i++) {
                if(i == latchNum - 1){
                    doFindTeacher(studentList.subList(start, studentList.size()), latch);
                }else{
                    doFindTeacher(studentList.subList(start, start+step), latch);
                    start = start + step;
                }
            }

            //上面的切割方法,也可以这么写,更加简洁:
            for (int j = 0; j < studentList.size(); j += step) {
                doFindTeacher(studentList.subList(j, Math.min(j + step, studentList.size())), latch);
            }

            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("执行完成,耗时:" + (System.currentTimeMillis() - begin) + "ms");

        pool.shutdown();
    }

    private static void doFindTeacher(List<String> studentList, CountDownLatch latch){
        pool.execute(() -> {
            try{
                for(String student : studentList){
                    System.out.println("开始处理学生:" + student);

                    //模拟查数据库...等操作,查找学生的老师
                    Thread.sleep(3000);
                    System.out.println("teacher: " + student + "'s teacher");
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                latch.countDown();
            }
        });
    }


}

记住经典写法:    

//上面的切割方法,也可以这么写,更加简洁:  
for (int j = 0; j < studentList.size(); j += step) {
    doFindTeacher(studentList.subList(j, Math.min(j + step, studentList.size())), latch);
}
 

console:

开始处理学生:wangwu
开始处理学生:zhangsan
开始处理学生:lisi
teacher: zhangsan's teacher
teacher: wangwu's teacher
teacher: lisi's teacher
执行完成,耗时:3094ms

 

三、例子3:    

 1 package com.cy.test.thread;
 2 
 3 
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 import java.util.concurrent.ExecutorService;
 7 import java.util.concurrent.Executors;
 8 import java.util.concurrent.FutureTask;
 9 
10 public class TestMultiThread3 {
11     private static int minProcessCnt = 1;
12     private static int poolSize = 5;
13     private static ExecutorService pool = Executors.newFixedThreadPool(poolSize);
14 
15     /**
16      * 1.模拟,使用多线程,找到每个学生的老师名字
17      * 2.将老师们的名字返回,并且输出
18      * @param args
19      */
20     public static void main(String[] args) {
21         long begin = System.currentTimeMillis();
22 
23         List<String> studentList = new ArrayList<>();
24         studentList.add("zhangsan");
25         studentList.add("lisi");
26         studentList.add("wangwu");
27 
28         int size = studentList.size();
29         int perCnt = size / poolSize;
30         int step = Math.max(perCnt, minProcessCnt);
31         int pollCount = (size + step - 1) / step;       // 列表循环次数
32 
33         List<FutureTask<List<String>>> taskList = new ArrayList<>();
34         for (int i = 0; i < pollCount; i++) {
35             final int start = step * i;
36             final int end = (i == pollCount - 1) ? size : step * (i + 1);
37             FutureTask<List<String>> task = new FutureTask<>(() -> {
38                 return doFindTeacher(studentList, start, end);
39             });
40             taskList.add(task);
41             pool.execute(task);
42         }
43 
44         //拿到返回结果
45         List<String> teacherList = new ArrayList<>();
46         try {
47             for (FutureTask<List<String>> futureTask : taskList) {
48                 List<String> list = futureTask.get();
49                 teacherList.addAll(list);
50             }
51         }catch (Exception e){
52             e.printStackTrace();
53         }
54 
55         System.out.println(teacherList);
56 
57         System.out.println("TestMultiThread3 执行完成,耗时:" + (System.currentTimeMillis() - begin) + "ms");
58         pool.shutdown();
59     }
60 
61 
62     private static List<String> doFindTeacher(List<String> studentList, int start, int end) throws InterruptedException {
63         List<String> teacherList = new ArrayList<>();
64         for(int j=start; j<end; j++){
65             String student = studentList.get(j);
66             System.out.println("开始处理学生:" + student);
67 
68             //模拟查数据库...等操作,查找学生的老师
69             Thread.sleep(3000);
70             String teacher = student + "'s teacher";
71             teacherList.add(teacher);
72         }
73         return teacherList;
74     }
75 }

console:

1 开始处理学生:zhangsan
2 开始处理学生:wangwu
3 开始处理学生:lisi
4 [zhangsan's teacher, lisi's teacher, wangwu's teacher]
5 TestMultiThread3 执行完成,耗时:3080ms

 

posted on 2019-11-11 14:54  有点懒惰的大青年  阅读(1372)  评论(0)    收藏  举报