![](https://img-blog.csdnimg.cn/20201014180756724.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
并发编程
文章平均质量分 85
KDLin
这个作者很懒,什么都没留下…
展开
-
Java并发中的种种正确的Tips
78. 同步访问共享的可变数据本条主要是指出内存可见性,Java内存模型,重排序等机制引起可变对象共享的问题,这些都是并发的基础理论知识。有时候这些错误不容易分析:// Broken! - How long would you expect this program to run?public class StopThread { private static boolean stopRequested; public static void main(String[] args)原创 2022-04-12 11:04:15 · 214 阅读 · 0 评论 -
你真的懂得Java异常的正确使用姿势吗?
引言异常机制我们再熟悉不过,在开发环境中,它非常有用。它能帮我们的程序从错锁中恢复,也能在程序奔溃的时候方便我们定位异常原因。但大家在生产环境中会不会有这种感觉:这个异常究竟应该catch处理掉呢,还是应该抛给调用方?底层抛出来的异常,究竟在哪一层处理比较好?应该抛出什么异常?尽管我们会想,属于用户责任就应该抛给用户,但这里的边界,实际开发中很难界定。本文来回答这个问题,并且会给出异常机制相关的最佳实践。回忆一下异常的知识。其中:Error是严重的错误,例如内存耗尽,栈溢出等等,它属于非受检异原创 2022-04-03 15:12:41 · 354 阅读 · 0 评论 -
原子变量、无锁算法和非阻塞机制
原子变量锁使用起来比较方法,但是它存在一些问题:性能问题。尽管现代JVM对于锁进行了很多优化,但是在多线程下,线程上下文切换仍需要os的支持,这部分开销始终是无法避免的。在计算任务比较断的时候,线程上下文切换将占据极大的部分,发生激烈的竞争,影响性能。换句话来说,锁太重了。活跃性问题。一个线程失败,可能引起所有线程阻塞。volatile显然是一种非常轻量的同步操作,它不会引起上下文切换,但它无法支持复合操作,例如i++,看起来是一条指令,实际上是三条字节码指令。所以它也无法支持“测试并更新”这种原创 2022-03-31 10:09:52 · 836 阅读 · 0 评论 -
并发程序的测试
并发的测试并不容易,原因在于并发的不确定性——并发场景下,很多问题无法重现,甚至它还有一个专有的名词,“海森堡错误”。此外,对于Java来说,性能测试经常是比较困难的,这是由于JVM做了太多事,犹如一个黑箱,像垃圾回收,实时编译,提前编译等,对于性能的影响其实很大,要命的事,它们通常不是程序可控的范围,所以需要更加小心。正确性测试正确性测试有一部分是串行正确性——即,在串行环境下,我们通常考虑的该程序的种种不变性条件。例如初始容量,各种操作等等。这部分就不展开了,也没有什么特殊的。阻塞测试阻塞是并行原创 2022-03-27 18:58:02 · 4623 阅读 · 0 评论 -
避免活跃性问题
活跃性问题和安全性问题很接近,安全性问题会导致活跃性问题的出现,例如死锁。但活跃性问题还包括更多,例如饥饿(优先级出问题),响应慢,活锁等。大致就是程序活跃性上出现异常。死锁在os中,我们知道了死锁四个必要条件,以及如何从这四个条件进行预防——破坏必要条件其中之一。互斥。——资源一般都是互斥,这没办法改变。不可抢占。——支持中断的抢占式系统。环路等待。——资源编号,申请资源只能按序号升序,防止出现环路。占有与等待。——一次性分配所有资源。这里相当于从Java编程的角度队这个问题进行另一个角原创 2022-02-23 20:45:03 · 215 阅读 · 0 评论 -
Java线程池进阶
线程池是Executor框架的经典实现。本篇应该结合线程池原理解析来看。线程池的隐性耦合Executor将任务的提交和执行解耦,实际上就像大多数复杂的解耦过程一样,这种论断有些言过其实任务与执行策略之间,实际上存在一些隐形耦合,需要我们了解,才能在使用的过程避开。任务依赖任务之间最好独立存在,这有利于一致性和并发性。但现实是,这种依赖在少数情况下仍然存在,例如在任务中可能需要提交新的任务,这时候就可能引起长时间延迟、死锁等。任务影响了任务的执行策略。例如单线程池如果执行某个任务,这个任务又原创 2022-01-11 21:32:41 · 301 阅读 · 0 评论 -
如何正确地取消Java任务或服务?
引言取消正在执行的任务、线程、服务,并不是那么容易。对于某个任务而言,为了支持取消操作,你不得不增加取消的代码,而且不一定支持阻塞;对于服务而言更是如此,你不清楚服务内部是依赖什么实现,所以就无法正常取消。(例如,内部可能是阻塞队列,可能是多个Task)任务取消取消一个任务,或一段程序,最容易想到的操作是增加判断标志,每次执行的时候判断,否则退出程序。但自定义的变量并不能解决阻塞问题。例如下面代码,如果在循环中阻塞了,那么它永远无法判断取消标志。while(!cancelled) { do som原创 2022-01-07 20:48:42 · 1589 阅读 · 0 评论 -
VarHandle,可变句柄解析
JDK 9中新增的库,是java.util.concurrent.atomic和sun.misc.Unsafe操作的等价替代。VarHandle是通用的对象的域的引用句柄,提供原子的操作方法。直接看用法即可。// 对象域private volatile int state;private volatile Thread runner;private volatile WaitNode waiters;// 通用句柄private static final VarHandle STATE;pr原创 2022-01-03 12:40:32 · 521 阅读 · 0 评论 -
ScheduledExecutor和DelayQueue,Java任务延迟执行的秘密
引言Timer类的解析中提到,Timer类的缺陷:单线程Timer只有一个任务执行线程,如果某个TimerTask耗时较久,影响其他任务Timer不会捕获执行TimerTask时所抛出的异常,由于Timer是单线程,所以一旦出现异常,则线程就会终止,其他任务也得不到执行。系统时间敏感性,由于Timer中使用了currentTimeMillis做参考,所以系统时间变化会使得任务发生变化所以在JDK1.5后大家就抛弃了Timer,一般使用ScheduledThreadPoolExecutor。原创 2022-01-02 16:46:32 · 991 阅读 · 0 评论 -
FutureTask原理解析
引言我们都知道Runable接口,它非常简单。但是它有一个问题——无法获取执行结果,以及一旦可以获取执行结果,什么时候可以获取执行结果?public interface Runnable { public abstract void run();}FutureTask就是为了解决这个问题的,将Runnable包装为FutureTask之后,就可以get获取任务执行结果,如果任务没有执行完,那么当前线程就会阻塞。FutureTask确实非常好用,但我一直以来都比较好奇,将Runnable包原创 2022-01-02 11:09:58 · 975 阅读 · 0 评论 -
Timer类原理解析,任务延迟执行
APITimer类用于延迟任务的执行。schedule(TimerTask task, **long **delay),指定延迟时间schedule(TimerTask task, Date time),指定时间schedule(TimerTask task, **long **delay, **long **period),指定延迟时间和重复周期schedule(TimerTask task, Date firstTime, **long **period),指定初始时间和重复周期源码解读原创 2022-01-02 11:08:07 · 1289 阅读 · 0 评论