Java并发之阻塞队列LinkedBlockingQueue学习
文章转自:https://blog.csdn.net/javazejian/article/details/77410889
概述使用方法阻塞队列概要阻塞队列与我们平常接触的普通队列(LinkedList或ArrayList等)的最大不同点,在于阻塞队列支持阻塞添加和阻塞删除方法。
阻塞添加所谓的阻塞添加是指当阻塞队列元素已满时,队列会阻塞加入元素的线程,直队列元素不满时才重新唤醒线程执行元素加入操作。
阻塞删除阻塞删除是指在队列元素为空时,删除队列元素的线程将被阻塞,直到队列不为空再执行删除操作(一般都会返回被删除的元素)
由于Java中的阻塞队列接口BlockingQueue继承自Queue接口,因此先来看看阻塞队列接口为我们提供的主要方法
1234567891011121314151617181920212223242526272829303132333435public interface BlockingQueue<E> extends Queue<E> { //将指定的元素插入到此队列的尾部(如果立即可行且不会超过该队列的容量) //在成功 ...
01.ThreadLocal的基础知识学习
概述文章参考:https://www.jianshu.com/p/1342a879f523
在java的多线程模块中,ThreadLocal是经常被提问到的一个知识点,提问的方式有很多种,可能是循序渐进也可能是就像我的题目那样,因此只有理解透彻了,不管怎么问,都能游刃有余。
这篇文章主要从以下几个角度来分析理解
ThreadLocal是什么从名字我们就可以看到ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
从字面意思来看非常容易理解,但是从实际使用的角度来看,就没那么容易了,作为一个面试常问的点,使用场景那也是相当的丰富:
在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。
线程间数据隔离
进行事务操作,用于存储线程事务信息。
数据库连接,Session会话管理。
现在相信你已经对ThreadLocal有一个大致的认识了,下面我们看看如何用?
ThreadLocal怎么用既然 ...
为什么将ThreadLocal变量设置为private static
[TOC]
概述文章参考:https://blog.csdn.net/silyvin/article/details/79551635
https://www.zhihu.com/question/35250439
在JDK源码中这样写到,为什么呢?
1<tt>ThreadLocal</tt> instances are typically private static fields in classes that wish to associate state with a thread。
首先,使用private只是Java的通用编程习惯。与ThreadLocal并没有本质性的关系,所以这里我们不做分析。
其实,ThreadLocal一般会使用static进行修饰。这样做既有好处也有坏处。好处是这样在一定程度上可以避免错误。至少可以避免重复创建TSO(Thread Specific Object 即ThreadLoca所关联的对象)所导致的浪费
缺点是:这样正好形成内存泄漏所需要的条件
下面,我们就来详细的分析一下:
我们知道ThreadLocal类的目的 ...
01.Java的并发锁学习
概述Java中锁的分类:
乐观锁和悲观锁
独占锁和共享锁
互斥锁和读写锁
公平锁和非公平锁
可重入锁
自旋锁
分段锁
锁升级(无锁|偏向锁|轻量级锁|重量级锁)
锁优化技术(锁粗化、锁消除)
乐观锁和悲观锁悲观锁
悲观锁对应于生活中悲观的人,悲观的人总是想着事情往坏的方向发展。
举个生活中的例子,假设厕所只有一个坑位了,悲观锁上厕所会第一时间把门反锁上,这样其他人上厕所只能在门外等候,这种状态就是「阻塞」了。
回到代码世界中,一个共享数据加了悲观锁,那线程每次想操作这个数据前都会假设其他线程也可能会操作这个数据,所以每次操作前都会上锁,这样其他线程想操作这个数据拿不到锁只能阻塞了。
在 Java 语言中 synchronized 和 ReentrantLock等就是典型的悲观锁,还有一些使用了 synchronized 关键字的容器类如 HashTable 等也是悲观锁的应用。
乐观锁
乐观锁 对应于生活中乐观的人,乐观的人总是想着事情往好的方向发展。
举个生活中的例子,假设厕所只有一个坑位了,乐观锁认为:这荒郊野外的,又没有什么人,不会有人抢我坑位的,每次关门上锁多浪费时间, ...
02.Java并发之CAS原理相关
文章参考:https://objcoding.com/2018/11/29/cas/
文章参考:https://blog.csdn.net/m0_37941483/article/details/103028270
文章参考:https://zhuanlan.zhihu.com/p/35158220
概述在 Java 并发领域,我们解决并发安全问题最粗暴的方式就是使用 synchronized 关键字了,但它是一种独占形式的锁,属于悲观锁机制,性能会大打折扣。volatile 貌似也是一个不错的选择,但 volatile 只能保持变量的可见性,并不保证变量的原子性操作。
CAS 全称是 compare and swap,即比较并交换,它是一种原子操作,同时 CAS 是一种乐观机制。java.util.concurrent 包很多功能都是建立在 CAS 之上,如 ReenterLock 内部的 AQS,各种原子类(包括AtomicInteger),其底层都用 CAS来实现原子操作。
如何解决并发安全问题在我们认识 CAS 之前,我们是通过什么来解决并发带来的安全问题呢?volatile ...
Java随机数之ThreadLocalRandom学习
[TOC]
线程的状态Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态),Running(运行状态),Blocked(阻塞状态),Dead(死亡状态)。
New:新建状态,当线程创建完成时为新建状态,即new Thread(…),还没有调用start方法时,线程处于新建状态。
Runnable:就绪状态,当调用线程的的start方法后,线程进入就绪状态,等待CPU资源。处于就绪状态的线程由Java运行时系统的线程调度程序(thread scheduler)来调度。
Running:运行状态,就绪状态的线程获取到CPU执行权以后进入运行状态,开始执行run方法。
Blocked:阻塞状态,线程没有执行完,由于某种原因(如,I/O操作等)让出CPU执行权,自身进入阻塞状态。
Dead:死亡状态,线程执行完成或者执行过程中出现异常,线程就会进入死亡状态。
二、wait/notify/notifyAll方法的使用1、wait方法:
JDK中一共提供了这三个版本的方法,
(1)wait()方法的作用是将当前运行的线程挂起(即让其进 ...
Java随机数之ThreadLocalRandom学习
[TOC]
问题描述与分析:
为了获取Crash日志,项目中实现了UncaughtExceptionHandler接口对未知异常进行捕获并上传到服务器中,同时停止App运行。在Android5.0以下系统一直未出现过问题,但是突然发现在Android 5.0以上的机器中这段代码出现了java.lang.InternalError: Thread starting during runtime shutdown(更多异常信息见最后部分的附录),在stackoverflow中得到了一些帮助:这个问题是因为线程开启的太晚了!
什么时候开启线程才算得上“太晚了”呢?
在我的项目中UncaughtExceptionHandler实现类捕获到异常时(也就是UncaughtExceptionHandler接口的uncaughtException方法执行时),开启了一个线程用于上传崩溃日志,而在线程中上传崩溃日志时创建了HttpClient发送网络请求。HttpClient创建时设置了ThreadSafeClientConnManager来管理连接,而在ThreadSafeClientConnMana ...
01.面试题-T1 T2 T3 多个线程异步转同步问题
文章转自: https://blog.csdn.net/s751167520/article/details/107512281
概述在实际业务场景中,经常会遇到多个线程调用不同的子系统,某些子系统之间的调用需要通过顺序性来保证数据的一致性。也是一个比较经典的多线程面试题。
有这样一个面试题:如何保证T1,T2,T3三个线程顺序执行。
使用Joinjoin的作用Thread类中的join方法的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行。当我们调用某个线程的这个方法时,这个方法会挂起调用线程,直到被调用线程结束执行,调用线程才会继续执行。
join源代码分析1234567891011121314151617181920212223242526public final synchronized void join(long millis) throws InterruptedException { // 获取当前基础四件 long base = System.currentTimeMillis(); long now = ...
Java随机数之ThreadLocalRandom学习
[TOC]
刚看到TimeUnit.SECONDS.sleep()方法时觉得挺奇怪的,这里怎么也提供sleep方法?
1234567public void sleep(long timeout) throws InterruptedException { if (timeout > 0) { long ms = toMillis(timeout); int ns = excessNanos(timeout, ms); Thread.sleep(ms, ns); }}
结果一看源码,原来是对Thread.sleep方法的包装,实现是一样的,只是多了时间单位转换和验证,然而TimeUnit枚举成员的方法却提供更好的可读性,这可能就是当初创建TimeUnit时提供sleep方法的原因吧,大家都知道sleep方法很常用,但经常要使用一个常量保存sleep的时间,比如3秒钟,我们代码通常会这样写:
1private final int SLEEP_TIME = 3 * 1000; //3 sec ...
Java随机数之ThreadLocalRandom学习
[TOC]
文章参考:https://blog.csdn.net/a314773862/article/details/54095819
自旋锁、阻塞锁、可重入锁、悲观锁、乐观锁、读写锁、偏向所、轻量级锁、重量级锁、锁膨胀、对象锁和类锁
1、自旋锁自旋锁可以使线程在没有取得锁的时候,不被挂起,而转去执行一个空循环,(即所谓的自旋,就是自己执行空循环),若在若干个空循环后,线程如果可以获得锁,则继续执行。若线程依然不能获得锁,才会被挂起。
2、阻塞锁有线程,通过竞争,进入运行状态。。JAVA中,能够进入\退出、阻塞状态或包含阻塞锁的方法有 ,synchronized 关键字(其中的重量锁),ReentrantLock,Object.wait()\notify()
3、可重入锁可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁
123456789101112131415161718192021222324252627282930313233343 ...