使用线程池的invokeAll 加速任务处理

需求说明:

        1.有很多的学生列表,这些学生来自不同学校不同年级和不同班级。先根据学校、年级和班级对学生进行分组。

       分组后打印绩点最好的一个学生的信息。

代码如下:

  


package yc.po;


public class Student implements Comparable<Student>{

    private String name;

    private int age;

    private String schoolCode;

    private String schoolName;

    private String gradeName;

    private String gradeCode;

    private String className;

    private String classCode;

    private String address;

    private double point;

    @Override
    public int compareTo(Student o) {
        return o.getPoint()> this.getPoint() ? 1 :0;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSchoolCode() {
        return schoolCode;
    }

    public void setSchoolCode(String schoolCode) {
        this.schoolCode = schoolCode;
    }

    public String getSchoolName() {
        return schoolName;
    }

    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }

    public String getGradeName() {
        return gradeName;
    }

    public void setGradeName(String gradeName) {
        this.gradeName = gradeName;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getGradeCode() {
        return gradeCode;
    }

    public void setGradeCode(String gradeCode) {
        this.gradeCode = gradeCode;
    }

    public String getClassCode() {
        return classCode;
    }

    public void setClassCode(String classCode) {
        this.classCode = classCode;
    }

    public double getPoint() {
        return point;
    }

    public void setPoint(double point) {
        this.point = point;
    }

    @Override
    public String toString() {
        return "学生姓名:"+ name + " 年龄:" + age
                + " 学校:" + schoolName + " 年级:" + gradeName
                + " 班级:" + className + " 绩点:" + point;
    }

}

import org.springframework.util.CollectionUtils;
import yc.po.Student;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

public class ExecuteStudentService {


    private static final int THREAD_POOL_NUMBER = 20;

    public static void main(String[] args) {

        ExecuteStudentService studentService = new ExecuteStudentService();

        List<Student> studentList =  new ArrayList<>();
        Student student1 = new Student();
        student1.setAge(20);
        student1.setName("张三");
        student1.setSchoolCode("A1");
        student1.setSchoolName("A学校");
        student1.setGradeName("1年级");
        student1.setGradeCode("G1");
        student1.setClassName("5班");
        student1.setClassCode("C5");
        student1.setPoint(4.0);
        student1.setAddress("中国A省B市C县D村E栋");
        studentList.add(student1);

        Student student2 = new Student();
        student2.setAge(20);
        student2.setName("李四");
        student2.setSchoolCode("A1");
        student2.setSchoolName("A学校");
        student2.setGradeName("1年级");
        student2.setGradeCode("G1");
        student2.setClassName("5班");
        student2.setClassCode("C5");
        student2.setPoint(3.5);
        student2.setAddress("中国A省B市C县D村F栋");
        studentList.add(student2);

        Student student3 = new Student();
        student3.setAge(20);
        student3.setName("王二");
        student3.setSchoolCode("B2");
        student3.setSchoolName("B学校");
        student3.setGradeName("2年级");
        student3.setGradeCode("G2");
        student3.setClassName("3班");
        student3.setClassCode("C3");
        student3.setPoint(3.8);
        student3.setAddress("中国A省B市G县Y村Z栋");
        studentList.add(student3);

        Student student4 = new Student();
        student4.setAge(20);
        student4.setName("麻子");
        student4.setSchoolCode("B2");
        student4.setSchoolName("B学校");
        student4.setGradeName("2年级");
        student4.setGradeCode("G2");
        student4.setClassName("3班");
        student4.setClassCode("C3");
        student4.setPoint(4.0);
        student4.setAddress("中国A省B市U县V村W栋");
        studentList.add(student4);

        studentService.handle(studentList);
    }


    public void handle(List<Student> studentList) {

        if (CollectionUtils.isEmpty(studentList)) {
            //log
            return;
        }
        long start = System.currentTimeMillis();

        //先用stream流对student进行分组
        Map<String, List<Student>> studentMap =
                studentList.stream().collect(Collectors.groupingBy(this::fetchGroupKey));
        Iterator<Map.Entry<String, List<Student>>> iterator = studentMap.entrySet().iterator();
        CountDownLatch countDownLatch = new CountDownLatch(studentMap.size());
        ExecutorService exec = Executors.newFixedThreadPool(THREAD_POOL_NUMBER);
        List<Callable<Boolean>> taskList = new ArrayList<Callable<Boolean>>();
        while (iterator.hasNext()) {
            List<Student> detailNext = iterator.next().getValue();
            Callable<Boolean> callable = invokeStudentByThread(detailNext, countDownLatch);
            taskList.add(callable);
        }
        try {
            //log
            exec.invokeAll(taskList);
        } catch (InterruptedException ex) {
            //log
            Thread.currentThread().interrupt();
        } catch (Exception ex) {
            //log
        } finally {
            exec.shutdown();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException ex) {
            //log
            Thread.currentThread().interrupt();
        }
        System.out.println("方法结束,记时" + String.valueOf(System.currentTimeMillis() - start));

    }

    //根据学校、年级、班级对学生进行分组
    private String fetchGroupKey(Student student) {
        return student.getSchoolCode() + student.getGradeCode() + student.getClassCode();
    }

    private Callable<Boolean> invokeStudentByThread(final List<Student> studentList, CountDownLatch countDownLatch) {
        if (CollectionUtils.isEmpty(studentList)) {
            return null;
        }
        Callable<Boolean> callable = () -> {
            Collections.sort(studentList);
            //打印年级绩点最好的一位学生
            System.out.println(studentList.get(0));
            return true;

        };
        countDownLatch.countDown();
        return callable;
    }


}

打印结果:

注意: 这里直接使用newFixedThreadPool 固定线程池去做了。但是按照JAVA阿里规约的话,其实是需要自定义一个的。

因为newFixedYThreadPool使用的是无界队列,这样最大线程数就会失效。他无界队列的数量是Integer.MAX_VALUE。

所以可能会造成OOM。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,使用线程池可以方便地开启多线程来处理任务。Java提供了几种常见的线程池创建方式,其中推荐使用ThreadPoolExecutor的构造器来创建适合业务场景的线程池。\[1\] 常见的线程池创建方式包括: 1. FixedThreadPool(固定线程池):线程池的大小一旦达到固定数量就会保持不变,适用于需要控制并发线程数量的场景。 2. SingleThreadExecutor(单线程化的线程池):只有一个线程的线程池任务按照提交的次序顺序执行,适用于需要按顺序执行任务的场景。 3. CachedThreadPool(可缓存线程池):线程池的大小可以根据需要自动调整,适用于需要处理大量短期任务的场景。 使用线程池的好处是可以提前创建好多个线程,放入线程池中,使用时直接获取,使用完后放回池中,避免频繁创建和销毁线程,实现线程的重复利用。线程池能够独立负责线程的创建、维护和分配,提高了线程的执行效率和资源利用率。\[2\]\[3\] #### 引用[.reference_title] - *1* *2* *3* [java多线程(线程池使用总结](https://blog.csdn.net/domine/article/details/127342754)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值