java 多线程: Thread 并发访问-代码块同步synchronized {};String作为被锁的对象
方法同步的弊端
方法同步的时候,如果一个方法需要线程安全控制的代码速度其实很快,但是还有其他的业务逻辑代码耗时非常长(比如网络请求),这样所有的线程就在这一块就等待着了,这样造成了极大的资源浪费如果并发量很大,可能会造成系统崩溃。(并发的线程遇到synchronized同步的方法,变成串行....)
并发访问-代码块同步
语法:
synchronized (要锁住的对象) {
并发执行且不耗时的业务计算代码;
}
代码示例: 方法同步比代码块同步耗时天壤地别
import java.util.HashSet; import java.util.Set; /** * @ClassName ThreadSyncCode * @projectName: object1 * @author: Zhangmingda * @description: XXX * date: 2021/4/22. */ public class ThreadSyncCode { //子线程类外公共用来计算的变量 private static int num = 0; //子线程对象 private static class MyRannable implements Runnable { @Override public void run() { //这里synchronized 导致耗时的IO操作也变为串行 /** * 模拟网络IO,磁盘IO耗时等待操作 */ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } /** * 避免多线程同时计算的代码块改为同步代码块。变为多线程到此串行执行;上面的IO耗时操作仍然并行 */ synchronized (getClass()){ for (int i=0; i<1000; i++){ num++; } } System.out.println(Thread.currentThread().getName() + " num result:" + num); } } public static void main(String[] args) { Set<Thread> threads = new HashSet<>(); MyRannable myRannable = new MyRannable(); for (int i=0; i<5; i++){ threads.add(new Thread(myRannable,"线程"+i)); } threads.forEach(thread -> thread.start()); try { Thread.sleep(6000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("main num result:" + num); } }
方法同步IO耗时串行导致长达5S出结果。而代码块同步耗时1S多结束。
String作为被锁的对象
import java.util.HashSet; import java.util.Set; /** * @ClassName ThreadMultiObjectSyncStringLock * @projectName: object1 * @author: Zhangmingda * @description: XXX * date: 2021/4/22. */ public class ThreadMultiObjectSyncStringLock { private static int num = 0; private static class MyThread extends Thread{ private String lock; public MyThread(String name, String lock) { super(name); this.lock = lock; } @Override public void run() { synchronized (lock){ for (int i=0; i<1000; i++){ num++; } System.out.println(Thread.currentThread().getName() + " num:" + num); } } } public static void main(String[] args) { //String锁对象 String lock = "LOCK"; //存放线程的集合 Set<MyThread> myThreads = new HashSet<>(); //向集合添加线程实例 for (int i=0; i<5; i++){ myThreads.add(new MyThread("T" +i, lock)); } //启动所有线程 myThreads.forEach(myThread -> myThread.start()); //稍等时间主线程查看结果 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "num Result:" + num); //5000完全正确 } }
结果:最终打印出来的num的值就是5000,结果是正确的。但是我们发现我们在for循环创建我们的线程的时候,我们定义了5次lock,但是实际上这些lock是同一个对象(指向的是同一个内存地址),因为在JAVA中,字符串具有常量缓存的功能。所以会被锁起来。
分类:
Java
posted on 2021-04-22 19:15 zhangmingda 阅读(193) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2020-04-22 深入理解css中position属性及z-index属性 https://www.cnblogs.com/zhuzhenwei918/p/6112034.html