很多时候并发需要考虑线程安全,但也有很多时候和线程安全毛关系都没有,因为并发最大的作用是并行,线程安全仅仅是并发的一个子话题。

例如常常会用于并发运算,并发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.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet; import study.model.school.StudentExamScoreSummary; /**
* @author luzhifei
*
*/
public class ConcurrentListRunable implements Runnable { private List<StudentExamScoreSummary> scoreList;
private Map<String, Boolean> flag; public ConcurrentListRunable(List<StudentExamScoreSummary> list, Map<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;
}
} try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
flag.put(courseName, true);
} public static void main(String[] args) {
int tty = 10;
String[] courses = new String[] { "数学", "语文", "物理", "政治", "哲学" };
Map<String, Boolean> flag = new HashMap<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);
String scoreTxt = item.getStudentId().toString() + "-【语文】" + df.format(item.getLanScore()) + " 【数学】"
+ df.format(item.getMathScore()) + " 【物理】" + df.format(item.getPhysicalScore()) + " 【政治】"
+ df.format(item.getPoliticsScore()) + " 【哲学】" + df.format(item.getPhilosophyScore()) + " |平均成绩:"
+ df.format(avgScore);
System.out.println(scoreTxt);
} // 排序
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-【语文】94.6 【数学】67.6 【物理】38.0 【政治】47.2 【哲学】35.3   |平均成绩:56.5
1-【语文】23.2 【数学】89.8 【物理】70.7 【政治】68.9 【哲学】49.3   |平均成绩:60.4
2-【语文】36.6 【数学】19.1 【物理】21.8 【政治】36.4 【哲学】75.6   |平均成绩:37.9
3-【语文】89.6 【数学】14.4 【物理】44.4 【政治】80.6 【哲学】07.1   |平均成绩:47.2
4-【语文】82.0 【数学】18.2 【物理】70.2 【政治】63.9 【哲学】17.4   |平均成绩:50.4
5-【语文】27.4 【数学】04.2 【物理】37.7 【政治】17.8 【哲学】20.1   |平均成绩:21.5
6-【语文】10.5 【数学】64.8 【物理】68.7 【政治】21.0 【哲学】97.2   |平均成绩:52.4
7-【语文】12.4 【数学】98.9 【物理】95.8 【政治】03.7 【哲学】56.3   |平均成绩:53.4
8-【语文】40.3 【数学】48.7 【物理】53.7 【政治】61.4 【哲学】42.9   |平均成绩:49.4
9-【语文】70.1 【数学】39.3 【物理】41.6 【政治】77.6 【哲学】87.3   |平均成绩:63.2
排序------------------------------------------
5 平均成绩:21.5
2 平均成绩:37.9
3 平均成绩:47.2
8 平均成绩:49.4
4 平均成绩:50.4
6 平均成绩:52.4
7 平均成绩:53.4
0 平均成绩:56.5
1 平均成绩:60.4
9 平均成绩:63.2

注意事项:

1.StudentExamScoreSummary必须实现Comparable接口,因为测试代码使用TreeSet

TreeSet<StudentExamScoreSummary> ts = new TreeSet<StudentExamScoreSummary>(sList); 
以上代码调用的构造函数是:
public TreeSet(Collection<? extends E> c) {
        this();
        addAll(c);
    }
这个构造函数要求入参必须实现Comparable接口(如果参数不是简单的java类型)。

2.Collections.synchronizedList的结果要求手动调用sychronized

   否则可能会线程不安全。

3.代码仅仅是为了演示使用5个线程各自生成成绩,不考虑效率问题。高效且正确的做法应该是分别计算5个不相干的List。

我们需要使用并发list的时候,正常情况下,多数是因为以下理由:

  • 对list的操作仅仅占据了很少的计算资源,线程更多的时候是做其它更耗费资源的事情
  • 为了实现异步操作

java并发和排序的简单例子(Runnable+TreeSet)的更多相关文章

  1. Java并发(10)- 简单聊聊JDK中的七大阻塞队列

    引言 JDK中除了上文提到的各种并发容器,还提供了丰富的阻塞队列.阻塞队列统一实现了BlockingQueue接口,BlockingQueue接口在java.util包Queue接口的基础上提供了pu ...

  2. Java并发:ThreadLocal的简单介绍

    作者:汤圆 个人博客:javalover.cc 前言 前面在线程的安全性中介绍过全局变量(成员变量)和局部变量(方法或代码块内的变量),前者在多线程中是不安全的,需要加锁等机制来确保安全,后者是线程安 ...

  3. [Java Web] 4、JavaScript 简单例子(高手略过)

    内容概览: JavaScript简介 JavaScript的基本语法 JavaScript的基本应用 JavaScript的事件处理 window对象的使用 JavaScript简介: JavaScr ...

  4. 【Java】Java日志框架Logback的简单例子

    常用的日志框架 SLF4J,全称Simple Logging Facade for Java,即Java简单日志外观框架,顾名思义,它并非具体的日志实现,而是日志外观框架 java.util.logg ...

  5. [转载]使用java.lang.Process类的简单例子

    FROM: http://segmentfault.com/blog/lidonghao/1190000000372192 ProcessBuilder类是J2SE 1.5在java.lang中新添加 ...

  6. rabbit的简单搭建,java使用rabbitmq queue的简单例子和一些坑

    一 整合 由于本人的码云太多太乱了,于是决定一个一个的整合到一个springboot项目里面. 附上自己的项目地址https://github.com/247292980/spring-boot 以整 ...

  7. Java连接数据库 #07# MyBatis Generator简单例子

    MyBatis Generator是一个可以帮助我们免去手写实体类&接口类以及XML的代码自动生成工具. 下面,通过一个简单的例子介绍MyBatis Generator如何使用. 大体流程如下 ...

  8. java并发:AQS的简单理解

    简介: AQS全称 AbstractQueuedSynchronizer,提供了一个基于FIFO(先进先出)队列,可以用于构建锁或者其他相关同步装置的基础框架. ReentrantLock.Semap ...

  9. Java产生死锁的一个简单例子

    思路是创建两个字符串a和b,再创建两个线程A和B,让每个线程都用synchronized锁住字符串(A先锁a,再去锁b:B先锁b,再锁a),如果A锁住a,B锁住b,A就没办法锁住b,B也没办法锁住a, ...

  10. JAVA JDBC 增删改查简单例子

    1.数据库配置文件jdbc.properties driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test username= ...

随机推荐

  1. WPF 通过 EXIF 设置和读取图片的旋转信息

    本文将告诉大家如何在 WPF 里面设置图片的 EXIF 信息,包括如何设置图片的旋转信息,以及如何读取 EXIF 的内容 值得一提的是在 WPF 里面,默认的图片渲染信息是无视 System.Phot ...

  2. Django之路由层、视图层、模板层介绍

    一.Django请求生命周期 1.路由层urls.py Django 1.11版本 URLConf官方文档 1.1 urls.py配置基本格式 from django.conf.urls import ...

  3. Oracle、达梦:同一数据库边查询边插入的两种方式

    1.方式1 插入的表需要构建好 -- 建表:6秒 500毫秒:抽数据100万:10秒 640毫秒.11秒 189毫秒 insert into T_HUGE_COMPRESS (ID, NAME) ( ...

  4. 史上功能最全的Java权限认证框架!

    大家好,我是 Java 陈序员.权限认证是我们日常开发绕不过的话题,这是因为我们的应用程序需要防护,防止被窜入和攻击. 在 Java 后端开发中,实现权限认证有很多种方案可以选择,一个拦截器.过滤器也 ...

  5. 【git】建立分支

    1.git clone现有的项目 git clone git@github.com:zhangshengdong/Zflask.git 2.建立关联 git remote add origin git ...

  6. Sermant在异地多活场景下的实践

    本文分享自华为云社区<Sermant在异地多活场景下的实践>,作者:华为云开源. Sermant社区在1.3.0和1.4.0版本相继推出了消息队列禁止消费插件和数据库禁写插件,分别用于解决 ...

  7. ansible(6)--ansible的copy和fetch模块

    1. copy模块 功能:从 ansible 服务端主控端复制文件到远程主机: copy模块的主要参数如下: 参数 说明 src 复制的源文件路径,若源文件为目录,默认进行递归复制,如果路劲以&quo ...

  8. uniapp中使用极光推送

    1.注册极光账号 2.注册几个主流手机厂商的开发者账号(注册手机厂商,可以保证app进程不在的时候走厂商通道推送消息) 3.配置uniapp极光插件 https://ext.dcloud.net.cn ...

  9. leaflet利用hotline实现河流差值渲染热力图

    实现效果(这里做了1条主河道和5个支流): 核心代码使用了Leaflet.hotline插件,github下载地址链接 详情见我之前整理的一篇文章介绍河流热力图 核心代码逻辑: // 处理河流数据以及 ...

  10. ES6常用知识点笔记

    ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准. 因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015(简称ES2015).虽然浏览器在不 ...