首页
关于
友链
Search
1
wlop 4K 壁纸 4k8k 动态 壁纸
1,470 阅读
2
Nacos持久化MySQL问题-解决方案
932 阅读
3
Docker搭建Typecho博客
752 阅读
4
滑动时间窗口算法
728 阅读
5
Nginx反向代理微服务配置
699 阅读
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
登录
Search
标签搜索
java
javase
docker
java8
springboot
thread
spring
分布式
mysql
锁
linux
redis
源码
typecho
centos
git
map
RabbitMQ
lambda
stream
少年
累计撰写
189
篇文章
累计收到
24
条评论
首页
栏目
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
页面
关于
友链
搜索到
1
篇与
的结果
2022-04-24
线程不安全的类与写法
线程不安全的类与写法线程不安全的类:类的对象可以同时被多个线程访问,比如抛出异常,逻辑错误。下面介绍一些常见的类。StringBuilderStringBuilder线程不安全的类代码示例package com.yanxizhu.demo.concurrency.threadUnSafetyClass; import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 线程不安全的类:StringBuilder * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/24 9:01 * @version: 1.0 */ @Slf4j @UnThreadSafety public class DemoStringBuilder { //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; //累加总和 private static StringBuilder stringBuilder = new StringBuilder(); public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { executorService.execute(()->{ try { semaphore.acquire(); update(); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("字符长度Length=【{}】",stringBuilder.length()); } /** * 累加 */ private static void update(){ stringBuilder.append(1); } }每次输出字符长度不一样,也不等于5000StringBuffer线程安全的类代码示例package com.yanxizhu.demo.concurrency.threadUnSafetyClass; import com.yanxizhu.demo.concurrency.annotation.ThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 线程安全的类:StringBuffer * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/24 9:06 * @version: 1.0 */ @Slf4j @ThreadSafety public class DemoStringBuffer { //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; //累加总和 private static StringBuffer stringBuffer = new StringBuffer(); public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { executorService.execute(()->{ try { semaphore.acquire(); update(); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("字符长度Length=【{}】", stringBuffer.length()); } /** * 累加 */ private static void update(){ stringBuffer.append(1); } }输出结果:每次都是长度为5000.StringBuffer为什么线程安全,看源码 @Override @HotSpotIntrinsicCandidate public synchronized StringBuffer append(int i) { toStringCache = null; super.append(i); return this; }因为StringBuffer所有的方法操作都加了synchronized。区别StringBuffer由于加了synchronized,性能上有损耗,没有StringBuilder性能高,在线程封闭中,堆栈封闭时,一般处理字符串局部变量时用StringBuilfer就行了。SimpleDateFormat线程不安全的类代码示例package com.yanxizhu.demo.concurrency.threadUnSafetyClass; import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety; import lombok.extern.slf4j.Slf4j; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 线程不安全类: SimpleDateFormat * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/24 9:18 * @version: 1.0 */ @Slf4j @UnThreadSafety public class DemoSimpleDateFormat { private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyyMMMdd"); //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { executorService.execute(()->{ try { semaphore.acquire(); update(); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); } /** * 累加 */ private static void update(){ try { simpleDateFormat.parse("20220424"); } catch (ParseException e) { log.error(e.getMessage()); } } }输出结果: at java.base/java.lang.Double.parseDouble(Double.java:543) at java.base/java.text.DigitList.getDouble(DigitList.java:169) at java.base/java.text.DecimalFormat.parse(DecimalFormat.java:2126) at java.base/java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1933) at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1541) at java.base/java.text.DateFormat.parse(DateFormat.java:393) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.update(DemoSimpleDateFormat.java:57) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.lambda$main$0(DemoSimpleDateFormat.java:40) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) Exception in thread "pool-1-thread-824" java.lang.NumberFormatException: For input string: "E.0220E0" at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054) at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110) at java.base/java.lang.Double.parseDouble(Double.java:543) at java.base/java.text.DigitList.getDouble(DigitList.java:169) at java.base/java.text.DecimalFormat.parse(DecimalFormat.java:2126) at java.base/java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1933) at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1541) at java.base/java.text.DateFormat.parse(DateFormat.java:393) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.update(DemoSimpleDateFormat.java:57) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.lambda$main$0(DemoSimpleDateFormat.java:40) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) Exception in thread "pool-1-thread-717" java.lang.NumberFormatException: multiple points at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1890) at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110) at java.base/java.lang.Double.parseDouble(Double.java:543) at java.base/java.text.DigitList.getDouble(DigitList.java:169) at java.base/java.text.DecimalFormat.parse(DecimalFormat.java:2126) at java.base/java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1933) at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1541) at java.base/java.text.DateFormat.parse(DateFormat.java:393) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.update(DemoSimpleDateFormat.java:57) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.lambda$main$0(DemoSimpleDateFormat.java:40) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) Exception in thread "pool-1-thread-671" java.lang.NumberFormatException: For input string: "" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.base/java.lang.Long.parseLong(Long.java:702) at java.base/java.lang.Long.parseLong(Long.java:817) at java.base/java.text.DigitList.getLong(DigitList.java:195) at java.base/java.text.DecimalFormat.parse(DecimalFormat.java:2121) at java.base/java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1933) at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1541) at java.base/java.text.DateFormat.parse(DateFormat.java:393) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.update(DemoSimpleDateFormat.java:57) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.lambda$main$0(DemoSimpleDateFormat.java:40) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) Exception in thread "pool-1-thread-805" java.lang.NumberFormatException: multiple points at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1914) at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110) at java.base/java.lang.Double.parseDouble(Double.java:543) at java.base/java.text.DigitList.getDouble(DigitList.java:169) at java.base/java.text.DecimalFormat.parse(DecimalFormat.java:2126) at java.base/java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1933) at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1541) at java.base/java.text.DateFormat.parse(DateFormat.java:393) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.update(DemoSimpleDateFormat.java:57) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.lambda$main$0(DemoSimpleDateFormat.java:40) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) Exception in thread "pool-1-thread-736" java.lang.NumberFormatException: For input string: ".20220424" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.base/java.lang.Long.parseLong(Long.java:678) at java.base/java.lang.Long.parseLong(Long.java:817) at java.base/java.text.DigitList.getLong(DigitList.java:195) at java.base/java.text.DecimalFormat.parse(DecimalFormat.java:2121) at java.base/java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1933) at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1541) at java.base/java.text.DateFormat.parse(DateFormat.java:393) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.update(DemoSimpleDateFormat.java:57) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.lambda$main$0(DemoSimpleDateFormat.java:40) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) Exception in thread "pool-1-thread-740" java.lang.NumberFormatException: multiple points at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1914) at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110) at java.base/java.lang.Double.parseDouble(Double.java:543) at java.base/java.text.DigitList.getDouble(DigitList.java:169) at java.base/java.text.DecimalFormat.parse(DecimalFormat.java:2126) at java.base/java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1933) at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1541) at java.base/java.text.DateFormat.parse(DateFormat.java:393) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.update(DemoSimpleDateFormat.java:57) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.lambda$main$0(DemoSimpleDateFormat.java:40) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) Exception in thread "pool-1-thread-695" java.lang.NumberFormatException: For input string: "E.0220" at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054) at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110) at java.base/java.lang.Double.parseDouble(Double.java:543) at java.base/java.text.DigitList.getDouble(DigitList.java:169) at java.base/java.text.DecimalFormat.parse(DecimalFormat.java:2126) at java.base/java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1933) at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1541) at java.base/java.text.DateFormat.parse(DateFormat.java:393) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.update(DemoSimpleDateFormat.java:57) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.lambda$main$0(DemoSimpleDateFormat.java:40) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) Exception in thread "pool-1-thread-888" java.lang.NumberFormatException: For input string: "202204242022042420220424" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.base/java.lang.Long.parseLong(Long.java:692) at java.base/java.lang.Long.parseLong(Long.java:817) at java.base/java.text.DigitList.getLong(DigitList.java:195) at java.base/java.text.DecimalFormat.parse(DecimalFormat.java:2121) at java.base/java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1933) at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1541) at java.base/java.text.DateFormat.parse(DateFormat.java:393) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.update(DemoSimpleDateFormat.java:57) at com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormat.lambda$main$0(DemoSimpleDateFormat.java:40) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834)虽然SimpleDateFormat是线程不安全的类,但是可以通过线程封闭中,堆栈封闭(栈封闭)方法,将SimpleDateFormat定义到局部变量中,每次是一个新对象,这样来保证线程安全。package com.yanxizhu.demo.concurrency.threadUnSafetyClass; import com.yanxizhu.demo.concurrency.annotation.ThreadSafety; import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety; import lombok.extern.slf4j.Slf4j; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 线程不安全类: SimpleDateFormat,通过堆栈封闭,实现线程安全。 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/24 9:18 * @version: 1.0 */ @Slf4j @ThreadSafety public class DemoSimpleDateFormatOk { //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { executorService.execute(()->{ try { semaphore.acquire(); update(); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); } /** * 通过线程封闭,将SimpleDateFormat定义在方法内,每次都是一个新的对象,来保证线程安全 */ private static void update(){ try { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyyMMMdd"); simpleDateFormat.parse("20220424"); } catch (ParseException e) { log.error(e.getMessage()); } } }输出结果:输出5000条,一样的。09:27:17.633 [pool-1-thread-461] ERROR com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormatOk - Unparseable date: "20220424" 09:27:17.633 [pool-1-thread-460] ERROR com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormatOk - Unparseable date: "20220424" 09:27:17.634 [pool-1-thread-452] ERROR com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormatOk - Unparseable date: "20220424" 09:27:17.634 [pool-1-thread-445] ERROR com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormatOk - Unparseable date: "20220424" 09:27:17.634 [pool-1-thread-453] ERROR com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoSimpleDateFormatOk - Unparseable date: "20220424" 。。。。。joda.time第三方包中DateTimeFormatter代码示例package com.yanxizhu.demo.concurrency.threadUnSafetyClass; import com.yanxizhu.demo.concurrency.annotation.ThreadSafety; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import java.util.Date; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 线程安全的类:Joda-time包里面的DateTimeFormatter需要单独导入 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/24 9:31 * @version: 1.0 */ @Slf4j @ThreadSafety public class DemoJodaTime { private static DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyyMMdd"); //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(clientsTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(concurrencyTotal); for (int i = 0; i < clientsTotal; i++) { final int count = i; executorService.execute(()->{ try { semaphore.acquire(); update(count); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); } /** * 通过线程安全对象dateTimeFormatter处理 */ private static void update(int count){ Date date = DateTime.parse("20220424", dateTimeFormatter).toDate(); log.info("{},{}", count, date); } }输出结果:有5000条,线程安全的09:45:06.164 [pool-1-thread-1947] INFO com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoJodaTime - 1946,Sun Apr 24 00:00:00 CST 2022 09:45:06.154 [pool-1-thread-491] INFO com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoJodaTime - 490,Sun Apr 24 00:00:00 CST 2022 09:45:06.184 [pool-1-thread-2943] INFO com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoJodaTime - 2942,Sun Apr 24 00:00:00 CST 2022 09:45:06.169 [pool-1-thread-1911] INFO com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoJodaTime - 1910,Sun Apr 24 00:00:00 CST 2022 09:45:06.169 [pool-1-thread-616] INFO com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoJodaTime - 615,Sun Apr 24 00:00:00 CST 2022 09:45:06.168 [pool-1-thread-2551] INFO com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoJodaTime - 2550,Sun Apr 24 00:00:00 CST 2022 09:45:06.144 [pool-1-thread-1415] INFO com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoJodaTime - 1414,Sun Apr 24 00:00:00 CST 2022 09:45:06.154 [pool-1-thread-4611] INFO com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoJodaTime - 4610,Sun Apr 24 00:00:00 CST 2022 09:45:06.169 [pool-1-thread-4760] INFO com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoJodaTime - 4759,Sun Apr 24 00:00:00 CST 2022 09:45:06.167 [pool-1-thread-2388] INFO com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoJodaTime - 2387,Sun Apr 24 00:00:00 CST 2022 09:45:06.184 [pool-1-thread-3990] INFO com.yanxizhu.demo.concurrency.threadUnSafetyClass.DemoJodaTime - 3989,Sun Apr 24 00:00:00 CST 2022 。。。。。ArrayList线程不安全的代码示例package com.yanxizhu.demo.concurrency.threadUnSafetyClass; import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety; import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.units.qual.A; import org.joda.time.DateTime; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 线程不安全类:ArrayList * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/24 9:52 * @version: 1.0 */ @Slf4j @UnThreadSafety public class DemoArrayList { private static List<Integer> list = new ArrayList<>(); //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { final int count = i; executorService.execute(()->{ try { semaphore.acquire(); update(count); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("list size:{}", list.size()); } /** * 通过线程安全对象dateTimeFormatter处理 */ private static void update(int count){ list.add(count); } }输出结果:每次输出ist长度不同,线程不安全的。HashSet线程不安全类代码示例package com.yanxizhu.demo.concurrency.threadUnSafetyClass; import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.HashSet; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 线程不安全类:HashSet * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/24 9:52 * @version: 1.0 */ @Slf4j @UnThreadSafety public class DemoHashSet { private static Set<Integer> set = new HashSet<>(); //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { final int count = i; executorService.execute(()->{ try { semaphore.acquire(); update(count); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("set size:{}", set.size()); } /** * 通过线程安全对象dateTimeFormatter处理 */ private static void update(int count){ set.add(count); } }输出结果:每次长度不同,不是5000,线程不安全。HashMap线程不安全的代码示例package com.yanxizhu.demo.concurrency.threadUnSafetyClass; import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; /** * @description: 线程不安全类:HashMap * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/24 9:52 * @version: 1.0 */ @Slf4j @UnThreadSafety public class DemoHashMap { private static Map<Integer, Integer> map = new HashMap(); //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(concurrencyTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal); for (int i = 0; i < clientsTotal; i++) { final int count = i; executorService.execute(()->{ try { semaphore.acquire(); update(count); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("map size:{}", map.size()); } /** * 通过线程安全对象dateTimeFormatter处理 */ private static void update(int count){ map.put(count, count); } }输出结果: 长度不是5000,每次长度不一样,线程不安全。总结:线程安全类对应的不只一个。后面专门说明。注意:先检查再执行这种类是线程不安全的,因为被分成2步了,if (condition(a)) { handle(1);}
2022年04月24日
230 阅读
0 评论
2 点赞