java并发和排序的简单例子(Runnable+TreeSet)
作者:互联网
很多时候并发需要考虑线程安全,但也有很多时候和线程安全毛关系都没有,因为并发最大的作用是并行,线程安全仅仅是并发的一个子话题。
例如常常会用于并发运算,并发i/o。
下文是一个练习笔记。
运行环境:windows 11,jdk17
1.Pojo--StudentExamScoreSummary
package study.model.school; import java.math.BigDecimal; import java.util.Date; public class StudentExamScoreSummary implements Comparable<StudentExamScoreSummary>{ private Integer id; private Integer studentId; private Integer theYear; private BigDecimal lanScore; private BigDecimal mathScore; private BigDecimal physicalScore; private BigDecimal politicsScore; private BigDecimal philosophyScore; private BigDecimal avgScore; private Date optime; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getStudentId() { return studentId; } public void setStudentId(Integer studentId) { this.studentId = studentId; } public Integer getTheYear() { return theYear; } public void setTheYear(Integer theYear) { this.theYear = theYear; } public BigDecimal getLanScore() { return lanScore; } public void setLanScore(BigDecimal lanScore) { this.lanScore = lanScore; } public BigDecimal getMathScore() { return mathScore; } public void setMathScore(BigDecimal mathScore) { this.mathScore = mathScore; } public BigDecimal getPhysicalScore() { return physicalScore; } public void setPhysicalScore(BigDecimal physicalScore) { this.physicalScore = physicalScore; } public BigDecimal getPoliticsScore() { return politicsScore; } public void setPoliticsScore(BigDecimal politicsScore) { this.politicsScore = politicsScore; } public BigDecimal getPhilosophyScore() { return philosophyScore; } public void setPhilosophyScore(BigDecimal philosophyScore) { this.philosophyScore = philosophyScore; } public BigDecimal getAvgScore() { return avgScore; } public void setAvgScore(BigDecimal avgScore) { this.avgScore = avgScore; } public Date getOptime() { return optime; } public void setOptime(Date optime) { this.optime = optime; } public BigDecimal calAvgScore() { return (this.lanScore.add(this.mathScore).add(this.physicalScore).add(this.politicsScore) .add(this.philosophyScore)).divide(new BigDecimal(5)); } @Override public int compareTo(StudentExamScoreSummary o) { return this.avgScore.compareTo(o.getAvgScore()); } }
2.线程和测试代码-ConcurrentListRunable
/** * */ package study.base.types.collection.list; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import study.model.school.StudentExamScoreSummary; /** * @author luzhifei * */ public class ConcurrentListRunable implements Runnable { private List<StudentExamScoreSummary> scoreList; DecimalFormat df = new DecimalFormat("#00.0"); ConcurrentHashMap<String, Boolean> flag; public ConcurrentListRunable(List<StudentExamScoreSummary> list, ConcurrentHashMap<String, Boolean> flag) { this.scoreList = list; this.flag = flag; } @Override public void run() { int len = scoreList.size(); String courseName = Thread.currentThread().getName(); for (int i = 0; i < len; i++) { StudentExamScoreSummary item = scoreList.get(i); double rscore = Math.random() * 100; BigDecimal dScore = new BigDecimal(rscore); dScore.setScale(1, RoundingMode.HALF_UP); synchronized (scoreList) { switch (courseName) { case "语文": item.setLanScore(dScore); break; case "数学": item.setMathScore(dScore); break; case "物理": item.setPhysicalScore(dScore); break; case "政治": item.setPoliticsScore(dScore); break; case "哲学": item.setPhilosophyScore(dScore); break; } } //System.out.println(item.getId().toString() + "-[" + courseName + "]" + df.format(dScore)); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized (flag) { flag.put(courseName, true); } } public static void main(String[] args) { int tty=10; String[] courses = new String[] { "数学", "语文", "物理", "政治", "哲学" }; ConcurrentHashMap<String, Boolean> flag = new ConcurrentHashMap<String, Boolean>(5); for (int i = 0; i < courses.length; i++) { flag.put(courses[i], false); } List<StudentExamScoreSummary> sList = new ArrayList<StudentExamScoreSummary>(); for (int i = 0; i < tty; i++) { StudentExamScoreSummary score = new StudentExamScoreSummary(); score.setId(i); score.setStudentId(i); score.setTheYear(2024); sList.add(score); } List<StudentExamScoreSummary> conList = Collections.synchronizedList(sList); ConcurrentListRunable job = new ConcurrentListRunable(conList, flag); List<Thread> jobs = new ArrayList<>(); for (int i = 0; i < courses.length; i++) { Thread t = new Thread(job, courses[i]); jobs.add(t); } for (int i = 0; i < courses.length; i++) { jobs.get(i).start(); } boolean isDone = false; while (isDone == false) { isDone = true; for (int i = 0; i < courses.length; i++) { if (flag.get(courses[i]) == false) { isDone = false; break; } } } DecimalFormat df = new DecimalFormat("#00.0"); for (int i = 0; i < sList.size(); i++) { StudentExamScoreSummary item = sList.get(i); BigDecimal avgScore = item.calAvgScore(); item.setAvgScore(avgScore); System.out.println(item.getStudentId().toString() + " 平均成绩:" + df.format(avgScore)); } // 排序 System.out.println("排序------------------------------------------"); TreeSet<StudentExamScoreSummary> ts = new TreeSet<StudentExamScoreSummary>(sList); for (Iterator<StudentExamScoreSummary> iter = ts.iterator(); iter.hasNext();) { StudentExamScoreSummary item=iter.next(); System.out.println(item.getStudentId().toString() + " 平均成绩:" + df.format(item.getAvgScore())); } } }
测试结果1:
0 平均成绩:48.8 1 平均成绩:53.7 2 平均成绩:43.8 3 平均成绩:56.9 4 平均成绩:64.9 5 平均成绩:49.9 6 平均成绩:51.0 7 平均成绩:58.4 8 平均成绩:61.3 9 平均成绩:48.5 排序------------------------------------------ 2 平均成绩:43.8 9 平均成绩:48.5 0 平均成绩:48.8 5 平均成绩:49.9 6 平均成绩:51.0 1 平均成绩:53.7 3 平均成绩:56.9 7 平均成绩:58.4 8 平均成绩:61.3 4 平均成绩:64.9
注意事项:
1.StudentExamScoreSummary必须实现Comparable接口,因为测试代码使用TreeSet
TreeSet<StudentExamScoreSummary> ts = new TreeSet<StudentExamScoreSummary>(sList);
以上代码调用的构造函数是:
public TreeSet(Collection<? extends E> c) {
this();
addAll(c);
}
这个构造函数要求入参必须实现Comparable接口(如果参数不是简单的java类型)。
2.ConcurrentHashMap和Collections.synchronizedList的结果要求手动调用sychronized
否则可能会线程不安全。
3.代码仅仅是为了演示使用5个线程各自生成成绩,不考虑效率问题。高效且正确的做法应该是分别计算5个不相干的List。
我们需要使用并发list的时候,正常情况下,多数是因为以下理由:
- 对list的操作仅仅占据了很少的计算资源,线程更多的时候是做其它更耗费资源的事情
- 为了实现异步操作
标签:Runnable,java,BigDecimal,item,new,成绩,public,TreeSet 来源: https://www.cnblogs.com/lzfhope/p/16328127.html