需求说明:
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。