![](https://img-blog.csdnimg.cn/20210521174609654.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
多线程
文章平均质量分 63
多线程,线程池
xyz
好记性不如烂笔头,DevOps这个Flag一定要立稳呀!
展开
-
多线程共同操初始化一个类,clinit方法会对静态资源加锁
当连个线程里的调用同一个类的创建实例,jvm的类加载器会保证静态资源只被加载一次(使用同一个类加载器的前提下),如果static代码块里写入一个死循环,则后一个被调用的线程会进入无限等待阶段public class Test{static{int i=0;while(true){Thread.sleep(1000); sout(i++);}}p...翻译 2021-07-18 11:22:27 · 224 阅读 · 0 评论 -
java synchronized 原理_Java基础-Synchronized原理
在多线程并发编程中Synchronized一直是元老级角色,很多人都会称呼它为重量级锁,但是随着Java SE1.6中为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁,以及锁的存储结构和升级过程。CAS(Compare and Swap),用于在硬件层面上提供原子性操作,在Intel处理器中,比较并交换通过指令cmpxchg实现。比较是否和给定的数值一致,如果一致则修改,不一致则不修改基础Java中的每一个对象都可以作为锁。对于同步方法,锁是当前实例对象。对于静态同步方法,锁转载 2021-07-07 22:53:29 · 54 阅读 · 0 评论 -
多线程死锁的产生以及如何避免死锁
一、死锁的定义多线程以及多进程改善了系统资源的利用率并提高了系统的处理能力。然而,并发执行也带来了新的问题–死锁。所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程将无法向前推进。下面我们通过一些实例来说明死锁现象先看生活中的一个实例:2个人一起吃饭但只有一双筷子,2人轮流吃(同时拥有2只筷子才能吃)。某一个时刻,一个拿了左筷子,另一个拿了右筷子,2个人都同时占用一个资源,等待另一个资源,这个时候甲在等待乙吃完并释放它占有的筷子,同理,乙也在等待甲吃完释放它占有的转载 2021-07-07 21:55:32 · 1611 阅读 · 0 评论 -
ReentrantLock(重入锁)功能详解和应用演示
例子public class ReentrantLockTest { public static void main(String[] args) throws InterruptedException { ReentrantLock lock = new ReentrantLock(); for (int i = 1; i <= 3; i++) { lock.lock(); } for(int转载 2021-07-07 21:46:02 · 815 阅读 · 0 评论 -
volatile底层原理详解
文章目录:一、volatile的作用1.1、volatile变量的可见性1.2、volatile变量的禁止指令重排序二、volatile的的底层实现2.1、 Java代码层面2.2、字节码层面2.3、JVM源码层面2.4、汇编层面2.5、硬件层面volatile关键字是Java虚拟机提供的最轻量级的同步机制。在多线程编程中volatile和synchronized都起着举足轻重的作用,没有这两者,也就没有那么多JUC供我们使用。本文会介绍volatile的作用,着重讲解volatile的底层实现转载 2021-07-07 21:36:39 · 477 阅读 · 0 评论 -
Java 同步方法和同步块,哪个是更好的选择
不太同意这一说法。 到底应该用同步块,同步方法完全取决于你的业务逻辑。 同步方法相当于锁了this,范围是整个方法。当你的业务不需要这么做或者不能这么做时,那就用同步块锁适当的对像。 换句话说,你把同步方法理解成同步块的简单写法就是了,业务上可以简单,那就简单点写。同步方法和同步代码块class Test{//同步方法 synchronizedmethod(){ //todo somthing }method2(){//同步代码块 ...转载 2021-07-06 00:20:26 · 597 阅读 · 0 评论 -
Java Timer类与Runnable之间的关系
java.util.Timer 是一个工具类,可以用于安排一个线程在未来的某个特定时间执行。Timer 类可以用安排一次性任务或者周期任务。java.util.TimerTask 是一个实现了 Runnable 接口的抽象类,我们需要去继承这个类来创建我们自己的定时任务并使用Timer 去安排它的执行。...原创 2021-07-07 21:37:49 · 246 阅读 · 0 评论 -
Java synchronized 和ReentrantLock 的区别
在JAVA多线程编程中,将需要并发执行的代码放在Thread类的run方法里面,然后创建多个Thread类的对象,调用start()方法,线程启动执行。当某段代码需要互斥时,可以用 synchronized 关键字修饰,这里讨论 synchronized 关键字修饰方法时,是如何互斥的。synchronized 修饰方法时锁定的是调用该方法的对象。它并不能使调用该方法的多个对象在执行顺序上互斥。下面举个具体的例子说明:Test.java 通过 implements Runnable 成为一个转载 2021-07-06 00:19:18 · 113 阅读 · 0 评论 -
为什么线程通信的方法wait(), notify()和notifyAll()被定义在Object类里
关于wait()、notify()的使用public class WaitDemo { public static Object object = new Object(); public static void main(String[] args) throws InterruptedException { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); ...转载 2021-07-06 00:21:45 · 345 阅读 · 0 评论 -
Java synchronized 和volatile 同步关键字对比
Java内存模型(JMM)提到这两个有关于线程的关键字,那么我们不得不提到Java的内存模型了(JMM),下面我们先看一下Java内存模型在处理多线程方面的工作原理图。Java内存模型(java Memory Model)描述了Java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。首先介绍两个概念可见性:一个线程对共享变量值的修改,能够及时地被其他线程看到。 共享变量:如果一个变量在多个线程的工作内存中都存在副本,那么这个变转载 2021-07-06 00:20:36 · 185 阅读 · 0 评论 -
Thread 类中的 yield 方法有什么作用?
使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。当前线程到了就绪状态,那么接下来哪个线程会从就绪状态变成执行状态呢?可能是当前线程,也可能是其他线程,看系统的分配了。...原创 2021-07-06 00:19:47 · 348 阅读 · 0 评论 -
Java 线程状态有哪些?
线程状态有 5 种,新建,就绪,运行,阻塞,死亡。关系图如下:1. 线程 start 方法执行后,并不表示该线程运行了,而是进入就绪状态,意思是随时准备运行,但是真正何时运行,是由操作系统决定的,代码并不能控制,2. 同样的,从运行状态的线程,也可能由于失去了 CPU 资源,回到就绪状态,也是由操作系统决定的。这一步中,也可以由程序主动失去 CPU 资源,只需调用 yield 方法。3. 线程运行完毕,或者运行了一半异常了,或者主动调用线程的 stop 方法,那么就进入死亡。死亡的线程不转载 2021-07-06 00:20:52 · 81 阅读 · 0 评论 -
java holdsLock()方法检测一个线程是否拥有锁
ava.lang.Thread中有一个方法叫holdsLock(),它返回true如果当且仅当当前线程拥有某个具体对象的锁Object o = new Object();@Testpublic void test1() throws Exception { new Thread(new Runnable() { @Override public void run() { synchronized(o) { ...转载 2021-07-06 00:20:58 · 436 阅读 · 0 评论 -
java中的同步集合与并发集合
同步集合可以简单地理解为通过synchronized来实现同步的集合。如果有多个线程调用同步集合的方法,它们将会串行执行。arrayList和vector、stack:1. Vector是线程安全的,源码中有很多的synchronized可以看出,而ArrayList不是。导致Vector效率无法和ArrayList相比2. ArrayList和Vector都采用线性连续存储空间,当存储空间不足的时候,ArrayList默认增加为原来的50%,Vector默认增加为原来的一倍3. Vector可以设转载 2021-07-06 00:21:14 · 109 阅读 · 0 评论 -
Java wait和notify为什么必须在同步块中
我们知道java的Object有wait和notify方法,如果要使用wait和notify的话,那么必须在synchronized块中,否则会抛出IllegalMonitorStateException。但是为什么必须在同步块中调用呢?直接wait,然后在notify不行吗?我一直存在这样的疑问,只到后来查到了Stack Overflow的一个回答,豁然开朗。大概翻译了下:假设我们要自定义一个blocking queue,如果没有使用synchronized的话,我们可能会这样写:class B转载 2021-07-06 00:21:51 · 305 阅读 · 0 评论 -
Java CopyOnWriteArrayList
一、简介1、ArrayList非线程安全的缺陷说到这个容器,从名字就可以看出,不得不说另外一个容器,也就是ArrayList。ArrayList是非线程安全的,也就是说在多个线程下进行读写,会出现异常。先举一个简单的例子,看看会出现什么问题,再来理解:我们运行一下就会出现错误:这里我们可以看到会抛出ConcurrentModificationException,这个异常是基于 fast-fail 机制的。不知道的可以私下了解一下。上面这个案例说明了ArrayList使..转载 2021-07-07 21:29:48 · 156 阅读 · 0 评论 -
HashTable、SynchronizedMap 和 ConcurrentHashMap 有什么区别
SynchronizedMap 一次性锁住整张表来保证线程安全,所以每次只能有一个线程来访问map。synchronizedMap实现了Map接口。 构造synchronizedMap时将this指针传递给监视器对象mutex,即同步方法块锁住的是synchronizedMap对象自身,并将方法代理在Map集合m的方法上。 synchronizedMap是Collections的私有静态内部类,可以通过Collecitons.synchronizedMap(Map...转载 2021-07-07 21:39:00 · 245 阅读 · 0 评论 -
java并发编程--- stop() 和 interrupt() 方法的主要区别
stop() 方法会真的杀死线程,不给线程喘息的机会,如果线程持有 ReentrantLock 锁,被 stop() 的线程并不会自动调用 ReentrantLock 的 unlock() 去释放锁,那其他线程就再也没机会获得 ReentrantLock 锁,这实在是太危险了。所以该方法就不建议使用了,类似的方法还有 suspend() 和 resume() 方法,这两个方法同样也都不建议使用了,所以这里也就不多介绍了。而 interrupt() 方法就温柔多了,interrupt() 方法仅仅是通知线转载 2021-07-07 21:40:25 · 660 阅读 · 0 评论 -
Java 中用到的线程调度算法是什么?
计算机通常只有一个CPU,在任意时刻只能执行一条机器指令,每个线程只有获得CPU的使用权才能执行指令.所谓多线程的并发运行,其实是指从宏观上看,各个线程轮流获得CPU的使用权,分别执行各自的任务.在运行池中,会有多个处于就绪状态的线程在等待CPU,JAVA虚拟机的一项任务就是负责线程的调度,线程调度是指按照特定机制为多个线程分配CPU的使用权.有两种调度模型:分时调度模型和抢占式调度模型。分时调度模型是指让所有的线程轮流获得cpu的使用权,并且平均分配每个...转载 2021-07-05 18:45:51 · 319 阅读 · 0 评论 -
Java CyclicBarrier原理
1、CyclicBarrier的简单概述现实生活中我们经常会遇到这样的情景,在进行某个活动前需要等待人全部都齐了才开始。例如吃饭时要等全家人都上座了才动筷子,旅游时要等全部人都到齐了才出发,比赛时要等运动员都上场后才开始。在JUC包中为我们提供了一个同步工具类能够很好的模拟这类场景,它就是CyclicBarrier类。利用CyclicBarrier类可以实现一组线程相互等待,当所有线程都到达某个屏障点后再进行后续的操作。下图演示了这一过程。CyclicBarrier字面意思是“可重复使用的栅转载 2021-07-05 18:40:01 · 145 阅读 · 0 评论 -
Java 关于多线程的一些思考
1.什么是原子操作,Java中的原子操作是什么?所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch。深入了解原子操作2. Java中的volatile关键是什么作用?volatile是Java提供的一种轻量级的同步机制。在并发编程的三个基本概念(原子性、可见性、有序性)中,volatile就保证了线程的可见性。当一个变量被volatile修饰后,表示着线程本地内存无效,当一个线程修改共享变量后他会立即被更新到主内存中,其转载 2021-07-05 18:35:24 · 86 阅读 · 0 评论 -
Java中CAS详解
在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁锁机制存在以下问题:(1)在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。(2)一个线程持有锁会导致其它所有需要此锁的线程挂起。(3)如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。volatile是不错的机制,但是volatile不能保证原子性。因此对于同步最终还是要回到锁机制上来。独占锁是一种悲观锁,synchronized就是一种转载 2021-07-05 18:10:02 · 92 阅读 · 0 评论 -
JAVA Semaphore详解
Semaphore(信号量):是一种计数器,用来保护一个或者多个共享资源的访问。如果线程要访问一个资源就必须先获得信号量。如果信号量内部计数器大于0,信号量减1,然后允许共享这个资源;否则,如果信号量的计数器等于0,信号量将会把线程置入休眠直至计数器大于0.当信号量使用完时,必须释放。实例代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16转载 2021-07-05 18:07:26 · 323 阅读 · 0 评论 -
Java CountDownLatch
1.背景:countDownLatch是在java1.5被引入,跟它一起被引入的工具类还有CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue。 存在于java.util.cucurrent包下。2.概念countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待转载 2021-07-05 18:01:19 · 46 阅读 · 0 评论 -
Java线程池是如何实现线程复用的?
信很多人都接触过线程池,我们知道线程池有核心线程和非核心线程之分,其中核心线程是一直存活在线程池中的,而非核心线程是在执行完任务之后超时销毁的。但是大家应该都知道一点,当Thread执行完Runnable任务之后就会销毁,而且就算执行完任务之后把线程挂起也没有办法再去执行其他任务,那线程池是如何做到核心线程复用的呢?下面就通过阅读源码的方法带大家了解背后的原因。推荐阅读之前的文章深入浅出Java(Android )线程池ThreadPoolExecutor大家可以对着这个流程图去学习源码,把这个图掌转载 2021-07-05 17:28:44 · 236 阅读 · 0 评论 -
为什么阿里巴巴Java开发手册中强制要求线程池不允许使用Executors创建
If you can NOT explain it simply, you do NOT understand it well enough 上一篇文章 线程数,射多少更舒适?从定性到定量的分析了如何创建正确个数的线程来最大化利用系统资源(其实就是几道小学数学题)。通常来讲,有了个这个知识点傍身,按需手动创建相应个数的线程就好但是现实中,你也许听过或者被要求:尽量避免手动创建线程,应使用线程池统一管理线程为什么会有这样的要求?背后的道理又是怎样的呢?顺着这个经验理论来推...转载 2021-07-05 17:19:21 · 271 阅读 · 0 评论 -
Java并发编程之线程池-Executor框架详解(Executor框架结构与框架成员)
一、什么是Executor框架?我们知道线程池就是线程的集合,线程池集中管理线程,以实现线程的重用,降低资源消耗,提高响应速度等。线程用于执行异步任务,单个的线程既是工作单元也是执行机制,从JDK1.5开始,为了把工作单元与执行机制分离开,Executor框架诞生了,他是一个用于统一创建与运行的接口。Executor框架实现的就是线程池的功能。二、Executor框架结构图解1、Executor框架包括3大部分:(1)任务。也就是工作单元,包括被执行任务需要实现的接口:Runnable接转载 2021-07-05 17:07:42 · 145 阅读 · 0 评论 -
Java 线程组ThreadGroup(已不推荐使用)
在Java中每一个线程都归属于某个线程组管理的一员,例如在主函数main()主工作流程中产生一个线程,则产生的线程属于main这个线程组管理的一员。简单地说,线程组就是由线程组成的管理线程的类,这个类是java.lang.ThreadGroup类。定义一个线程组,通过以下代码可以实现。ThreadGroup group=new ThreadGroup("group");Thread thread=new Thread(group,"the first thread of group");Thread原创 2021-07-05 16:53:16 · 679 阅读 · 0 评论 -
Java 活锁与死锁
死锁:是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。产生死锁的必要条件:1、互斥条件:所谓互斥就是进程在某一时间内独占资源。2、请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。3、不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。4、循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。活锁:任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,..转载 2021-07-05 16:49:35 · 147 阅读 · 0 评论 -
Java 多线程上下文切换
一、CPU时间片CPU时间片即CPU分配给每个线程的执行时间段,称作它的时间片。CPU时间片一般为几十毫秒(ms)。二、什么是上下文切换CPU通过时间片段的算法来循环执行线程任务,而循环执行即每个线程允许运行的时间后的切换,而这种循环的切换使各个程序从表面上看是同时进行的。而切换时会保存之前的线程任务状态,当切换到该线程任务的时候,会重新加载该线程的任务状态。而这个从保存到加载的过程称之为上下文切换。若当前线程还在运行而时间片结束后,CPU将被剥夺并分配给另一个线程。 若线程在时间片结束前阻转载 2021-07-05 16:42:03 · 534 阅读 · 0 评论 -
java 中的守护进程
在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守护线程的保姆:只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。User和Daemon两者几乎没有区别,唯一的不同之处就在于虚.转载 2021-07-05 16:38:42 · 3255 阅读 · 0 评论