打酱油的葫芦娃
一万年太久,只争朝夕!
展开
-
一文教会你HashMap为啥线程不安全(多图VIP版)
首先思考一下,为啥 HashMap 会存在线程安全性问题?有的人脱口而出,JDK7 的 HashMap 因为采用头插法,多线程环境下会造成死循环,JDK8 虽然改用了尾插法,但多线程环境下仍然存在丢失更新的问题,所以 HashMap 存在线程安全性问题。一听就是老八股人了,哈哈哈。但其实上面的答案并不全面,而且很容易误导编程的新手,让新手总以为 HashMap 只是因为死循环或者丢失更新的问题才导致的线程不安全。HashMap 之所以存在线程安全性问题,本质上是因为 HashMap 的"增删改"操作原创 2022-04-14 20:27:08 · 7275 阅读 · 2 评论 -
Thread类源码解读3--线程中断interrupt
线程中断是一个很重要的概念,通常,取消一个任务的执行,最好的,同时也是最合理的方法,就是通过中断。本篇我们主要还是通过源码分析来看看中断的概念。本文的源码基于JDK1.8Interrupt status & InterruptedExceptionjava线程的中断机制为我们提供了一个契机,使被中断的线程能够有机会从当前的任务中跳脱出来。而中断机制的最核心的两个概念就是interrupt status 和 InterruptedException。java中对于中断的大部分操作无外乎以下两原创 2022-03-07 23:45:43 · 4866 阅读 · 0 评论 -
Thread类源码解读2--线程状态及常用方法
本文源码基于jdk1.8 。线程状态在Thread类中, 线程状态是通过threadStatus属性以及State枚举类实现的:/* Java thread status for tools, * initialized to indicate thread 'not yet started' */private volatile int threadStatus = 0;public enum State { /** * Thread state for a threa原创 2022-03-07 23:44:11 · 4884 阅读 · 0 评论 -
Thread类源码解读1--如何创建和启动线程
本文源码基于jdk1.8 。Runnale接口我们看Thread类的定义知道,它实现了Runable接口public class Thread implements Runnable { ...}而Runnable接口的定义如下:@FunctionalInterfacepublic interface Runnable { public abstract void run();}它只有一个抽象方法run。同时,该接口还被@FunctionalInterface注解标注,原创 2022-03-06 10:03:31 · 5098 阅读 · 0 评论 -
Java停止线程的3种方式
在Java中有以下3种方式终止正在运行的线程:使用退出标志,使线程正常退出;使用stop()方法强行终止线程,不推荐使用该方法,JDK已声明弃用;使用interrupt方法中断线程。使用标志位在 run() 方法执行完毕后,该线程就终止了。但是在某些特殊的情况下,run() 方法会被一直执行;比如在服务端程序中可能会使用 while(true) { … } 这样的循环结构来不断的接收来自客户端的请求。此时就可以用修改标志位的方式来结束 run() 方法。public class Server原创 2022-03-04 11:14:39 · 8198 阅读 · 0 评论 -
Unsafe类详解
Java 不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe 类提供了硬件级别的原子操作。Unsafe 类在 sun.misc 包下,不属于 Java 标准。很多 Java 的基础类库,包括一些被广泛使用的高性能开发库都是基于 Unsafe 类开发,比如 Netty、Hadoop、Kafka 等。Unsafe 是用于在实质上扩展 Java 语言表达能力、便于在更高层(Java 层)代码里实现原本要在更低层(C 层)实现的核心库功能用的。这些功能包括裸内存的申请/释放/访问,低层硬件的.原创 2022-03-04 11:09:44 · 12730 阅读 · 0 评论 -
Java多线程系列--Future接口和CompletableFuture类
Future接口Future接口是Java 1.5引入的新特性,可以方便的用于异步结果的获取。接口定义如下:public interface Future<V> { // 取消提交的异步任务 boolean cancel(boolean mayInterruptIfRunning); // 判断异步任务是否已取消 boolean isCancelled(); // 判断异步任务是否已完成 boolean isDone(); /原创 2022-03-02 15:37:16 · 6211 阅读 · 0 评论 -
ScheduledThreadPoolExecutor源码解析
ScheduledThreadPoolExecutor是由Doug Lea大神出品,用于执行延时任务的线程池。public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService { }ScheduledThreadPoolExecutor继承了ThreadPoolExecutor,并自定义了延迟阻塞队列DelayedWork原创 2022-01-19 17:11:23 · 5214 阅读 · 0 评论 -
Java线程池详解3--线程池终止
线程池终止主要依靠以下2个命令:shutdown()shutdownNow()首先看一下shutdown方法:shutdownpublic void shutdown() { final ReentrantLock mainLock = this.mainLock; // 获取独占锁 mainLock.lock(); try { // 检查各worker是否可操作 checkShutdownAccess(); // 将线程池状态更新为SHUTDOWN advanceRu原创 2020-07-29 10:43:37 · 6847 阅读 · 0 评论 -
Java线程池详解2--任务提交及执行
ThreadPoolExecutor如何实现任务的提交和执行的呢?首先,看一下ThreadPoolExecutor的Worker内部类。WorkerThreadPoolExecutor定义了内部类Worker来表征线程池中的工作线程:// 继承了AQS,并实现了Runnable接口private final class Worker extends AbstractQueuedSynchronizer implements Runnable{ // 工作线程 final Thread原创 2020-07-29 10:42:53 · 6598 阅读 · 0 评论 -
Java线程池详解1--概述
线程池架构Java的线程池架构如下图所示:Executor接口该接口只提供了一个execute方法,该方法用于已提交的Runnable任务对象,该接口提供了任务提交和任务执行解耦的方法。void execute(Runnable command);ExecutorService接口ExecutorService主要在Executor上做了一些扩展。(1) 线程池关闭// 关闭线程池,该方法执行后,拒绝接受新任务,但之前提交的任务继续执行void shutdown();// 立即关闭原创 2020-07-29 10:42:03 · 4867 阅读 · 0 评论 -
Java并发工具类--Semaphore详解
Semaphore是啥?贴个官方解释:Semaphore用于限制可以访问某些资源(物理或逻辑的)的线程数目,其维护了一个许可证集合,有多少资源限制就维护多少许可证集合,假如这里有N个资源,那就对应于N个许可证,同一时刻也只能有N个线程访问。一个线程获取许可证就调用acquire方法,用完了释放资源就调用release方法。举例举个生活中的例子:某餐厅只有3张餐桌,而当前需要接待的客人有6桌,那么就需要领号排队,结束一桌进去一桌,此处餐桌就相当于Semaphore的许可证。通过代码实现上述过程原创 2020-07-22 17:34:36 · 5056 阅读 · 0 评论 -
Java并发工具类--CyclicBarrier详解
CyclicBarrier允许一组线程在到达某个栅栏点(common barrier point)互相等待,直到最后一个线程到达栅栏点,栅栏才会打开,处于阻塞状态的线程恢复继续执行。举例举个例子来说明CyclicBarrier的使用:比如吃鸡游戏4排,需要等4个队友均点击准备才可以开启比赛。public class CyclicBarrierTest { static class Player implements Runnable{ private String id;原创 2020-07-22 14:26:59 · 4873 阅读 · 0 评论 -
Java并发工具类--CountDownLatch详解
CountDownLatch是一个同步工具类,用来协调多个线程之间的同步。CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成一些任务,然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务。举个例子来说明CountDownLatch的使用:百米赛跑,10名运动员选手到达场地等待裁判口令,裁判一声口令,选手原创 2020-07-21 16:43:08 · 5180 阅读 · 0 评论 -
Java的AQS详解3--Condition接口
Condition定义了等待/通知两种类型的方法,当前线程调用这些方法时,需要提前获取到Condition关联的锁。Condition对象由Lock对象(调用Lock的newCondition()方法)创建出来的,换句话说,Condition是依赖Lock对象的。首先跟一下Condition的await方法:await需要注意的是:调用await方法的线程肯定是持有锁的线程,即同步队列的头节点。public final void await() throws InterruptedExceptio原创 2020-07-21 16:42:19 · 4851 阅读 · 0 评论 -
Java的AQS详解2--共享锁的获取及释放
上篇我们讲了Java的AQS详解1–独占锁的获取及释放,本篇接着讲共享锁的获取及释放。加锁共享锁加锁的方法入口为:public final void acquireShared(int arg) { if (tryAcquireShared(arg) < 0) doAcquireShared(arg);}tryAcquireShared(arg)尝试获取锁,由AQS的继承类实现。若返回值为负,证明获取锁失败,紧接着执行doAcquireShared(arg)方法。doAcquir原创 2020-06-06 16:32:20 · 5030 阅读 · 0 评论 -
Java的AQS详解1--独占锁的获取及释放
其实,很早之前就写过一篇浅谈Java的AQS,当时对AQS的运作机制有了大致的掌握,但可能源码还是没完全吃透,有些细节还是云里雾里。最近又过了一遍AQS源码,觉得体悟更深了些,怕时间久了遗忘掉,记录下来方便后面查阅。为避免篇幅较长,将这部分2篇来讲解,本文为第1篇,主要讲解AQS独占锁的获取及释放。加锁独占锁加锁的方法入口为acquire(int arg);public final void acquire(int arg) { if (!tryAcquire(arg) &&原创 2020-06-05 16:36:36 · 5162 阅读 · 0 评论 -
为何wait和notify方法必须加锁?
为何wait和notify方法必须加锁?是为了避免Lost Wake Up问题,即丢失唤醒问题。所谓Lost Wake Up,指的是:线程A调用wait()方法进入阻塞状态,接下来没有其他线程去唤醒线程A,或者其他线程唤醒的时机不对(早于线程A的wait()),导致线程A永远阻塞下去。下面以一个生产者和消费者的案例来说明上述问题。假如我们有两个线程,一个消费者线程,一个生产者线程。生产者线程的任务可以简化成将count加一,而后唤醒消费者;消费者则是将count减一,而后在减到0的时候陷入睡眠,.原创 2020-06-03 11:37:11 · 8826 阅读 · 1 评论 -
Java的锁机制--偏向锁、轻量锁、自旋锁、重量锁
基础知识线程切换代价Java的线程是映射到操作系统的原生线程之上的,如果阻塞或唤醒一个线程就需要操作系统介入,需要在用户态和内核态之间切换,该切换会消耗大量的系统资源,因为用户态和内核态均有各自专用的内存空间,专用的寄存器等,用户态切换至内核态需要传递很多变量、参数给内核,内核也需要保护好用户态切换时的一些寄存器值、变量等,以便内核态调用结束后切换回用户态继续工作。JVM1.6之前,Synchronized会导致争不到锁的线程直接进入阻塞状态,所以说其是一个重量级的同步操作,被称为重量锁。为了缓解上原创 2020-06-02 12:07:04 · 6942 阅读 · 0 评论 -
多线程环境下HDFS的FileSystem使用踩坑
最近用户反映项目现场某些Spark服务会莫名宕掉,作为组内的救火小王子,急速远程到现场服务器排查相关问题。打开宕掉服务的日志,发现该服务"遗言"如下:23:46:02.441 [Thread-3] INFO o.a.spark.storage.DiskBlockManager - Shutdown hook called23:46:02.441 [dispatcher-event-loop...原创 2020-04-02 20:42:15 · 8255 阅读 · 9 评论 -
Java的锁机制--Lock接口
synchronized关键字虽然可以解决大部分多线程锁的问题,但是仍旧存在下述问题:假如持有锁的某线程因等待长时IO或者其他原因阻塞,其他等待的线程无法响应中断,只能不断等待;多线程下只有读操作是不会发生冲突的,但synchronized关键字对读和写操作均一视同仁,所以当一个线程进行读取操作时,其他线程只能不断等待;使用synchronized关键字无法确认线程是否成功获取到锁。针...原创 2019-05-20 17:30:56 · 6547 阅读 · 1 评论 -
Java的锁机制--ReadWriteLock接口
ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,实际上独占锁是一种相对比较保守的锁策略,独占锁模式下的读/读、读/写、写/写操作都不能同时发生,这在一定程度上降低了吞吐量。然而读操作之间不存在数据竞争问题,如果读/读操作能够以共享锁的方式进行,那会进一步提升性能。为解决读写冲突问题,Doug Lea设计了ReadWriteLock接口,该接口只定义了两个方法:r...原创 2019-05-20 17:31:58 · 4907 阅读 · 1 评论 -
浅谈线程间的协作机制-Object的wait()/notify()及Condition的await()/signal()
注意:如无特殊说明,本文源码分析基于的Java JDK版本均为1.8。等待/通知机制假设这样的情景,只要线程A修改了某值value,则线程B则对新的value值进行某些操作,比较容易想到的方法是,线程B不断循环访问value,一旦感知到变化,则执行相应逻辑。// 线程Aset value = newValue// 线程Bfor(;;){ while(newValue != oldV...原创 2019-05-07 17:09:33 · 5358 阅读 · 1 评论 -
浅谈Java的AQS
所谓AQS,指的是AbstractQueuedSynchronizer,它提供了一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架,ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier等并发类均是基于AQS来实现的,具体用法是通过继承AQS实现其模板方法,然后将子类作为同步组件的内部类。了解一个框架最好的方式是读源码,说干就干。AQS是...原创 2019-05-05 18:54:22 · 7729 阅读 · 1 评论 -
聊一聊ThreadLocal是个啥东东
引言ThreadLocal提供了线程私有的局部变量,可以在整个线程存活的过程中随时取用,从而减少了在同一个线程内多个函数或者组件之间公共变量传递的复杂度。同时,由于ThreadLocal变量的线程私有性,故不存在并发线程安全的问题。要满足上述特性,需要解决3个问题:与线程绑定,实现私有性;提供合适的容器,方便变量的存取;设计合理的垃圾回收机制,避免内存泄露。实现原理为解决前2...原创 2019-04-30 15:34:37 · 5023 阅读 · 1 评论 -
ConcurrentHashMap揭秘-JDK1.7
引言HashMap是非线程安全的,而HashTable是线程安全的,但是HashTable实现同步的方法比较暴力,即在所有方法体上添加synchronized关键字,相当于所有读写线程均去读取一把锁,效率比较低下。另外一种同步Map的方法是使用Collections工具类:Collections.synchronized(new HashMap()该种方法与HashTable实现方式类似...原创 2019-05-28 14:57:12 · 4812 阅读 · 1 评论 -
Java并发编程--volatile关键字
引言很久之前就想写volatile关键字,但是迟迟没有动笔,主要是volatile涉及到的东西有点多,讲不清楚倒还好,就怕反而把读者绕晕了,哈哈。volatile关键字是为了保证内存可见性的,首先介绍并发编程中涉及到的3个问题:并发编程规则原子性原子具有不可分割性,所谓原子性,指的是一个或多个操作,要么全部执行且执行过程不会被任何因素打断,要么就全部执行,其与事务的语义是一致的。比如经...原创 2019-05-28 17:35:01 · 4794 阅读 · 1 评论 -
Java的锁机制---synchronsized关键字
引言高并发环境下,多线程可能需要同时访问一个资源,并交替执行非原子性的操作,很容易出现最终结果与期望值相违背的情况,或者直接引发程序错误。举个简单示例,存在一个初始静态变量count=0,两个线程分别对count进行100000次加1操作,期望的结果是200000,实际是这样的吗?写个程序跑下看看:public class CountWithoutSyn { private vol...原创 2019-05-20 17:29:56 · 5113 阅读 · 1 评论