首页 文章 精选 留言 我的

精选列表

搜索[高并发],共10000篇文章
优秀的个人博客,低调大师

Java并发编程 -- 单例模式线程安全问题

单例模式是指对一个对象进行一次实例化,然后全局都可以调用该实例化对象来完成项目的开发。 在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。 实现单例的不同方式 饿汉式单例 饿汉式单例是指在方法调用前,实例就已经创建好了。下面是实现代码: package com.thread.singleton; /** * 单例模式-- 饿汉式 * Created by Fant.J. * 2018/2/25 19:24 */ public class Singleton1 { /** 私有化构造方法,在外部不能实例化对象 */ private Singleton1(){} /** 在这里实例化 静态对象 (优点:不存在线程安全问题。 缺点:每次调用都实例化,占用空间) */ private static Singleton1 singleton1 = new Singleton1(); public static Singleton1 getInstance(){ return singleton1; } } 优点:不存在线程安全问题。 缺点:每次调用都实例化,占用空间 懒汉式单例 懒汉式单例是指在方法调用获取实例时才创建实例,因为相对饿汉式显得“不急迫”,所以被叫做“懒汉模式”。下面是实现代码: package com.thread.singleton; /** * 单例模式 -- 懒汉式 * Created by Fant.J. * 2018/2/25 19:30 */ public class Singleton2 { private Singleton2(){} private static Singleton2 instance; public synchronized static Singleton2 getInstance() { /* 下面这段代码 不是原子性操作 会出现线程安全问题 。**/ if (instance == null) { instance = new Singleton2(); } return instance; } } 在这段代码中,在if语句里面,就可能跑有多个线程同步判断和同步new。会产生线程安全问题。 解决方法: 给方法加上synchronized(变成单线程,影响性能) 给代码块加synchronized(双重检查加锁) 虽然2方法解决了性能问题, 但是还会有问题 。 问题来自 jvm 的优化:指令重排序(有兴趣了解) 我们可以在对象中添加volatile 关键字来 不让jvm对该 对象做优化 完善后的代码如下: package com.thread.singleton; /** * 单例模式 -- 懒汉式 * Created by Fant.J. * 2018/2/25 19:30 */ public class Singleton2 { private Singleton2(){} private static Singleton2 instance; public synchronized static Singleton2 getInstance() { /* 下面这段代码 不是原子性操作 会出现线程安全问题 。 解决方法:1.给方法加上synchronized(变成单线程,影响性能) 2.给代码块加synchronized(双重检查加锁) 虽然2方法解决了性能问题, 但是还会有问题 。 问题来自 jvm 的优化:指令重排序(有兴趣了解) 我们可以在对象中添加volatile 关键字来 不让jvm对该 对象做优化 **/ if (instance == null) { synchronized (Singleton2.class){ if (instance == null){ instance = new Singleton2(); } } } return instance; } }

优秀的个人博客,低调大师

Java并发编程实战系列7之取消与关闭

JAVA媒体提供任务机制来安全的终止线程。但是它提供了中断(interruption),这是一种写作机制,能够使一个线程终止另外一个线程。 一般来说没人希望立即终止,因为必要时总要先清理再终止。 开发一个应用能够妥善处理失败、关闭、取消等过程非常重要也有挑战。 7.1 任务取消 一定不要使用Thread.stop和suspend这些机制。 一种协作机制就是“标记位”。例如使用volatile类型的field来保存取消状态。 @ThreadSafe public class PrimeGenerator implements Runnable { private static ExecutorService exec = Executors.newCachedThreadPool(); @GuardedBy("this") private final List<BigInteger> primes = new ArrayList<BigInteger>(); private volatile boolean cancelled; public void run() { BigInteger p = BigInteger.ONE; while (!cancelled) { p = p.nextProbablePrime(); synchronized (this) { primes.add(p); } } } public void cancel() { cancelled = true; } public synchronized List<BigInteger> get() { return new ArrayList<BigInteger>(primes); } static List<BigInteger> aSecondOfPrimes() throws InterruptedException { PrimeGenerator generator = new PrimeGenerator(); exec.execute(generator); try { SECONDS.sleep(1); } finally { generator.cancel(); } return generator.get(); } } 1.1 中断 下面的例子会出现死锁,线程根本不会停止 class BrokenPrimeProducer extends Thread { private final BlockingQueue<BigInteger> queue; private volatile boolean cancelled = false; BrokenPrimeProducer(BlockingQueue<BigInteger> queue) { this.queue = queue; } public void run() { try { BigInteger p = BigInteger.ONE; while (!cancelled) queue.put(p = p.nextProbablePrime()); } catch (InterruptedException consumed) { } } public void cancel() { cancelled = true; } } interrupt 方法:中断目标线程。isInterrupted:返回目标线程的中断状态。静态的 interrupted方法:清除当前线程的中断状态,并返回它之前的值。大多数可中断的阻塞方法会在入口处检查中断状态 对中断操作(调用interrupt)的正确理解 他并不会真正的中断一个正在运行的线程,而只是发出中断请求,然后由线程在下一个合适的时候中断自己。比如,wait、sleep、 join等方法,当他们收到中断请求或开始执行时,发现某个已经被设置好的中断状态,则抛出异常interruptedException。 每个线程都有一个boolean类型的中断状态。当调用Thread.interrupt方法时,该值被设置为true,Thread.interruptted可以恢复中断。 阻塞库方法,例如sleep和wait、join都会检查中断,并且发现中断则提前返回,他们会清楚中断状态,并抛出InterruptedException。 但是对于其他方法interrupt仅仅是传递了中断的请求消息,并不会使线程中断,需要由线程在下一个合适的时刻中断自己。 通常,用中断是取消的最合理的实现方式。 上面的例子的改进方法就是 public class PrimeProducer extends Thread { private final BlockingQueue<BigInteger> queue; PrimeProducer(BlockingQueue<BigInteger> queue) { this.queue = queue; } public void run() { try { BigInteger p = BigInteger.ONE; while (!Thread.currentThread().isInterrupted()) queue.put(p = p.nextProbablePrime()); } catch (InterruptedException consumed) { /* Allow thread to exit */ } } public void cancel() { interrupt(); } } 7.1.2 中断策略 发生了中断,需要尽快退出执行流程,并把中断信息传递给调用者,从而使调用栈中的上层代码可以采取进一步的操作。当然任务也可以不需要放弃所有操作,可以推迟处理中断清楚,知道某个时机。 7.1.3 响应中断 传递异常 回复中断状态 public class NoncancelableTask { public Task getNextTask(BlockingQueue<Task> queue) { boolean interrupted = false; try { while (true) { try { return queue.take(); } catch (InterruptedException e) { interrupted = true; // fall through and retry } } } finally { if (interrupted) Thread.currentThread().interrupt(); } } interface Task { } } 7.1.6 处理不可中断的阻塞 例如Socket I/O或者内置锁都不能响应中断,这时候该如何做才能终止他们呢?可以通过重写Thread.interrupt方法,例如加入close的逻辑。 7.2 停止基于线程的服务 7.2.1 示例:日志服务 7.2.2 关闭ExecutorService 7.2.3 Poison Pill 例如CloseEvent机制或者POISON对象,来做特殊的识别,从而让程序自己处理停止操作,退出线程。 7.3 处理非正常的线程终止 7.4 JVM关闭 第8章 线程池的使用 一个很好的ThreadPoolExecutor源码分析文档 ThreadPoolExecutor UML图: image image image

优秀的个人博客,低调大师

老男孩教育每日一题-第96天-网站并发知识点:pv-并发与架构设计基础知识

你想建设一个能承受500万PV/每天的网站吗? 500万PV是什么概念? 服务器每秒要处理多少个请求才能应对?如何计算呢? 答案参考: PV是什么: PV是page view的简写。PV是指页面的访问次数,每打开或刷新一次页面,就算做一个pv。 计算模型: 每台服务器每秒处理请求的数量=((80%总PV量)/(24小时60分60秒40%)) / 服务器数量 。 其中关键的参数是80%、40%。表示一天中有80%的请求发生在一天的40%的时间内。 24小时的40%是9.6小时,有80%的请求发生一天的9.6个小时当中(很适合互联网的应用,白天请求多,晚上请求少)。 简单计算的结果: ((80%500万)/(24小时60分60秒40%))/1 = 115.7个请求/秒 ((80%100万)/(24小时60分60秒40%))/1 = 23.1个请求/秒 初步结论: 现在我们在做压力测试时,就有了标准,如果你的服务器一秒能处理115.7个请求,就可以承受500万PV/每天。 如果你的服务器一秒能处理23.1个请求,就可以承受100万PV/每天。 留足余量: 以上请求数量是均匀的分布在白天的9.6个小时中,但实际情况并不会这么均匀的分布,会有高峰有低谷。 为了应对高峰时段,应该留一些余地,最少也要x2倍,x3倍也不为过。 115.7个请求/秒2倍=231.4个请求/秒 115.7个请求/秒3倍=347.1个请求/秒 23.1个请求/秒2倍=46.2个请求/秒 23.1个请求/秒3倍=69.3个请求/秒 最终结论: 如果你的服务器一秒能处理231.4—347.1个请求/秒,就可以应对平均500万PV/每天。 如果你的服务器一秒能处理46.2—69.3个请求,就可以应对平均100万PV/每天。 说明: 这里说明每秒N个请求,就是QPS。因为我关心的是应用程序处理业务的能力。 备注 今天是每日一题陪伴大家的第96天,期待你的进步。 对于题目和答案的任何疑问,请在博客评论区留言。 往期题目索引 http://lidao.blog.51cto.com/3388056/1914205 本文转自 李导 51CTO博客,原文链接:http://blog.51cto.com/lidao/1948925

优秀的个人博客,低调大师

网易澄清前游戏管创业争议

网易近日发布声明称: 我们观察到近期媒体及社交媒体出现“网易前COO再创业”及与其相关的纠纷传闻等信息。经查,该人员已于2011年正式离职,其后在其他公司任职、创业等一切经历均与网易公司无关。其个人引发的争议与风波,均不代表网易立场。 据悉,网易所指的前COO为詹钟晖。9月4日,有网友在社交平台发现,詹钟晖正在为其创业项目的单机游戏新作招聘人才。 公开资料显示,詹钟晖于1999年加入网易,从程序员做起,历任在线游戏事业部总监、网易联合COO、网易COO,后于2011年离职创立简悦。2017年,简悦被阿里收购,2019年詹钟晖成立灵犀互娱,此后,他在灵犀长期担任游戏业务负责人。 2024年3月,詹钟晖发布内部邮件表示即将卸任。2025年,他发布朋友圈,表示自己将投身内容驱动的单机买断制游戏。2025年4月,詹钟晖成立广州钛麒数字科技有限公司,紫龙CEO王一任联合创始人。 此次引发舆论风波的是其今年4月创立的广州钛麒数字科技有限公司,据其自述,该公司当前主营赛道为“内容驱动的单机买断游戏”,并对外发布招聘意向。 近日,有网友发帖称,詹钟晖带队的单机项目在招聘时白嫖应聘者创意方案,并指控其人和游戏公司存在多项弊病。目前,詹钟晖尚未做出公开回应。

优秀的个人博客,低调大师

2024 年 Apache DolphinScheduler 社区光时刻

亲爱的朋友们,让我们把时间的快门按下,一起回顾这一年的点点滴滴。就像翻阅一本精彩的相册,每一张照片都记录着我们Apache DolphinScheduler社区的欢笑和泪水。那么,准备好了吗?让我们一起跳进时光机,回顾社区里2024年那些难忘的瞬间吧! 时光荏苒,新年将至,2025年,愿我们所有人的梦想照进现实,愿所有愿美好如期而至! 本文由 白鲸开源科技 提供发布支持!

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册