![](https://img-blog.csdnimg.cn/20201014180756918.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
多线程
Pr Young
一个踏实努力,充满激情的程序员!
展开
-
CountDownLatch
这是通过一个计数器来实现的,计数器初始化的值为线程的数量,每当一个线程完成了自己的任务之后,计数器的值就减去1,当计数器的值减为0的时候,表示所有线程都完成了任务,此时在CountDownLatch上等待的线程就可以执行了。这一行的时候会检查计数器的值,只要值不为0,当前线程(也就是主线程会进入阻塞态)(2) await()方法,当前线程进入到同步队列中进行等待,直到计数器的值减到0。(4)countDown() 方法,使计数器的值减1。每个线程执行完,计数器的值就减1,最后减为0。原创 2023-05-23 21:59:50 · 435 阅读 · 0 评论 -
AtomicInteger类
(5)compareAndSet(expect,update)//如果count的值等于预期值(第一个参数),那么就将count的值设置为update,如果不等于预期值,那就什么也不做。(2)getAndIncrement()先获取count的值,再将count的值+1。incrementAndGet()先将count的值+1,然后再获取count的值。decrementAndGet()先将count的值-1,然后再获取count的值。(1)get()方法获取值,set()方法获取值。原创 2023-04-28 17:14:29 · 162 阅读 · 0 评论 -
线程的生命周期以及sleep()方法和wait()方法
共享对象调用wait方法:obj.wait(),当前线程释A放锁,进入waiting阻塞状态,除非其他线程调用共享对象obj.notify()方法唤醒这个线程,线程A就会去竞争试图重新获得锁,如果获得锁就进入运行态,如果没有获得锁就进入blocked阻塞状态。线程休眠指定时间,不会释放锁,也就是线程即使休眠也是一直保持锁的所有权的,等休眠时间一过,马上进入运行态,不用再去和其他处于blocked状态的线程一起竞争锁。sleep方法和wait()方法的区别。t1我被唤醒了,我又重新开始运行了。原创 2023-04-26 17:42:38 · 909 阅读 · 0 评论 -
wait/notify方法 等待唤醒机制
先是线程1运行,然后执行到object.wait()的这一行的时候,线程1卡住了,进入到Object类的对象object的wait等待集合里,同时将object锁也释放掉。线程正在运行,调用这个线程的wait()方法,这个线程就会进入一个集合进行等待(这个集合的线程不会争抢cpu),此时线程的状态就是waiting。(2)thread.sleep()方法不会释放对象锁,是释放cpu,如果线程持有锁,那即使sleep()会使线程休眠,但是不会释放锁,两个都释放cpu,但是sleep不释放锁,wait释放锁。原创 2023-02-24 15:26:07 · 493 阅读 · 0 评论 -
自旋锁介绍
自旋锁的思想就是让线程在请求一个被锁定的共享数据时,不进入需要很大开销的阻塞状态,而是执行忙循环(也就是自旋)一段时间,如果在执行忙循环的时候,能够获得共享数据的锁,就不用进入阻塞状态了。执行忙循环(自旋)需要占用CPU时间,所以自旋锁只适用于共享数据被锁定的时间很短的场景。线程进入阻塞状态的开销很大,应当尽量避免进入阻塞状态。其实很多时候,共享数据只会被锁定很短一段时间。原创 2023-01-24 17:35:08 · 70 阅读 · 0 评论 -
ThreadLocal
这是因为threadlocal底层使用的数据结构是threadlocalmap,key是一个threadlocal对象的弱引用,当进行垃圾回收时,threadlocal对象被回收,于是key变成null,但是value还是有值的,因此这个value就无法通过key找到。ThreadLocal对象有两个方法set方法和get方法,所以每一个ThreadLocal对象都有set,get两个方法,用于给这个ThreadLocal对象设置值和取出值。1.通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。原创 2022-12-24 09:59:06 · 399 阅读 · 0 评论 -
AQS,AbstractQueuedSynchronizer
AbstractQueuedSynchronizer 抽象队列同步器是JUC最重要的基石内置一个FIFO队列,想要获取资源的线程在这个队列中进行排队原创 2022-12-03 18:45:48 · 89 阅读 · 0 评论 -
CAS,Compare and Set,比较并交换
Compare and Set,比较并交换(其实应该是比较并设置)还是得从JMM出发:线程将工作内存中的变量副本写到主内存,赋给共享变量的时候,先检查此时共享变量是不是自己期望的值,如果是自己期望的值,就将新值赋给共享变量,如果不是自己期望的值,此次赋值操作无效代码实现:原创 2022-12-03 18:03:10 · 142 阅读 · 0 评论 -
volatile
是java虚拟机提供的轻量级的同步机制(乞丐版的synchronized)具备三个性质:保证可见性,不保证原子性,禁止指令重排前置知识: java内存模型 (Java Memory Model) JMM_Pr原创 2022-12-03 17:00:55 · 401 阅读 · 0 评论 -
同步和异步
同步:发送了一个请求,需要等待返回,然后再发送下一个请求异步:发送了一个请求,不等待返回,随时可以再发送下一个请求显然:同步和异步最大的区别就在于:一个需要等待,一个不需要等待广播,就是一个异步例子。发起者不关心接收者的状态。不需要等待接收者的返回信息电话,就是一个同步例子。发起者需要等待接收者,接通电话后,通信才开始。需要等待接收者的返回信息当多线程共享某一资源的时候,需要使用同步机制原创 2022-12-03 10:50:34 · 97 阅读 · 0 评论 -
多线程交叉打印
问题:有3个线程,让这三个线程交替打印A,B,C。两个线程交叉打印一个打印A一个打印B 循环打印。打印完毕后,才能继续打印。这三个线程分别负责打印。之后,不能马上再次打印。我们需要有3个线程,原创 2022-11-04 21:31:35 · 716 阅读 · 0 评论 -
Monitor
注意:waitset中的Thread0和Thread1是之前获得过锁,但是条件不满足进入waiting状态的线程(wait-notify里会讲清楚这个问题)加了synchronized的对象会关联一个监视器monitor(怎么关联?这个对象的对象头的Mark Word中会被设置一个指向Monitor对象的指针)Thread2已经是Monitor的主人Owner了(Monitor只能有一个主人)Thread4也进入Monitor的阻塞队列EntryList。Synchronized的底层原理。原创 2022-11-04 12:23:40 · 125 阅读 · 0 评论 -
协程(也叫纤程)
Jvm里面有M个线程,而操作系统里面只有N个线程,通常M远远大于N,比如M=10000,N=10。Jvm里面本来有自己的线程栈(Pc Stack),但是在自己的线程栈基础上又建立了另一套线程栈。协程被称为“轻量级线程”、“微线程”、“纤程(fiber)”,线程中的线程等。简单来说可以认为协程是线程里不同的函数,这些函数之间可以相互。这十个线程就可以负责一万个JVM里面线程的同步和并发。这个建立在线程栈基础上的线程栈,就叫做协程。原创 2022-11-02 23:30:05 · 207 阅读 · 0 评论 -
守护线程介绍
将一个线程设置为守护线程的方法:在调用这个线程的start方法之前,先调用setDaemon方法。有一种特殊的线程,只要其守护的线程运行结束了,即使守护线程本身没有执行完,也会强制结束。垃圾回收线程就是一种守护线程,如果程序停止了,垃圾回收线程也会被强制停止。原创 2022-10-25 22:05:00 · 118 阅读 · 0 评论 -
第五篇文章:锁的分类
认为每次读取数据时都认为别人会修改数据,所以每次在读写数据时都会上锁,这样别人想读写这个数据时就会阻塞、等待直到拿到锁。非公平锁虽然放弃了锁的公平性,但是执行效率明显高于公平锁。非公平锁指JVM遵循随机、就近原则分配锁的机制。比较当前版本号与上一次的版本号,如果版本号一致,则更新,如果版本号不一致,则重复进行读、比较、写操作。独占锁:也叫互斥锁,每次只允许一个线程持有该锁,ReentrantLock为独占锁的实现。从获取资源的公平性角度可分为公平锁和非公平锁,锁从乐观和悲观的角度可分为乐观锁和悲观锁,原创 2022-10-02 00:51:40 · 310 阅读 · 0 评论 -
第三篇文章:死锁
两个线程在互相等待对方释放占有的资源,因此都处于阻塞态。如和避免死锁:银行家算法。原创 2022-09-30 17:55:33 · 254 阅读 · 0 评论 -
第一篇文章:创建线程的两种方式
由于java中类必须单继承,所以如果用第一种方式创建线程,那这个类就无法再继承其他类了,因此方式二是一种更常用的创建方式。方式二:搞一个类(比如叫MyThread),让它实现Runnable接口。方式一:搞一个类(比如叫MyThread)让它继承Thread类。原创 2022-09-30 00:35:17 · 99 阅读 · 0 评论 -
第一篇文章:进程和线程
某些进程内部还需要同时执行多个子任务。例如,我们在使用Word时,Word可以让我们一边打字,一边进行拼写检查,同时还可以在后台进行打印,我们把子任务称为线程。一个任务就是一个进程,浏览器就是一个进程,视频播放器是另一个进程,音乐播放器和Word也是进程。每个线程有自己单独的程序计数器,虚拟机栈,本地方法栈。一个进程可以包含一个或多个线程,但至少会有一个线程。一个进程内的多个线程共享这个进程的堆和方法区。原创 2022-09-30 00:30:17 · 153 阅读 · 0 评论 -
第二篇文章:线程的状态(生命周期) 五种状态和六种状态
这是因为一个线程一次在cpu上运行很短的时间(比如10~20ms,此时线程处于running状态),然后就要被切换下来放到调度队列的队尾(此时线程处于ready状态),由于线程在这两种状态之间切换的很快,所以区分这两种状态没什么意义。注意其中waiting状态和Time_Waiting状态之间的区别是waiting状态是一直。(2)除了有阻塞态,新加了新的状态:等待状态。等待状态,该线程等待的是其他线程通知或者中断。创建(初始),就绪,运行,阻塞,死亡。阻塞状态,该线程等待的是其他线程释放锁。原创 2022-09-30 00:18:02 · 379 阅读 · 0 评论 -
第一篇文章:在主方法中再开一个线程(主线程和副线程双线程并行)
java程序启动时实际上启动了一个JVM进程,在这个JVM进程里先启动主线程main()方法,然后在main方法中,可以启动其他线程。下面的程序总共有四条输出语句:我们分别给它们编号①②③④,这四条语句到底执行顺序是怎么样的呢?有没有可能是①④②③。这份代码,先是启动了主线程,执行 System.out.println("主线程开始运行");当存在两个线程:主线程和另一个我们自己创建的进程的时候,语句执行顺序问题。然后执行到test.start()这条语句的时候,启动了我们自己的线程(原创 2022-09-30 00:43:42 · 245 阅读 · 0 评论 -
并发和并行
并发说明你可以处理多个任务(但不一定是同时处理,可以是我先处理任务A,然后快速切换到去执行任务B,然后又快速切换到去执行任务C,然后又快速切换到去执行任务A.......),重点是。并行是不仅要具备多个任务的能力,还要能同时执行这些任务。所以显然,具备并行能力的一定具备并发能力。...原创 2022-08-27 10:35:40 · 62 阅读 · 0 评论 -
线程池一系列面试问题
【代码】线程池。原创 2022-08-27 01:45:56 · 495 阅读 · 0 评论 -
线程之间协作和通信
打个比方,现在有一张桌子D,一个放苹果的人A(生产者),一个吃苹果的人B(消费者),以及苹果C。现在有个标志flag,当标志为true的时候,B才可以去吃,吃了后,标志位变为false,通知A再去放,如果B没有吃,A就一直等待。整一个专门的池子(数据缓冲区),把生产出来的产品放这个池子里,比如你生产了100个,先预存在这个池子里面(生产者将生产好的数据放入缓冲区,消费者从缓冲区拿出数据)一位标志位,通过标志位来判断生产者能否放入产品(或者消费者能否取出产品)解决方法1:管程法(利用缓冲区解决)...原创 2022-08-27 01:29:32 · 47 阅读 · 0 评论 -
不用synchronized的另一种加锁方式:ReentrantLock类
【代码】不用synchronized的另一种加锁方式:ReentrantLock类。原创 2022-08-26 16:52:10 · 198 阅读 · 0 评论 -
第四篇文章:Synchronized
(1)锁住一个我们自己new出来的Object类对象。Synchronized关键字使用的三种情景(即。(2)锁住整个静态方法或者非静态方法。原创 2022-08-26 16:39:47 · 174 阅读 · 0 评论 -
线程优先级
线程的优先级用数字1~10来表示,数字越大优先级越高,默认每个线程的优先级是5。获取线程优先级的方法:getPriority()设置线程优先级的方法:setPriority()有一个线程调度器监控所有处于就绪状态的线程。线程调度器按照优先级决定执行哪一个线程。...原创 2022-08-26 14:27:15 · 107 阅读 · 0 评论 -
第二篇:线程的方法
本来是要执行1000次打印输出,但是执行到900次的时候,将调用我们写的线程的stop方法,将flag置为false,然后就不会再打印输出了。sleep(时间):表示当前线程阻塞的毫秒数,比如sleep(1000)就是当前线程阻塞1000ms,也就是1s,阻塞时间到了就进入就绪状态。可以看到在run方法里面,只有当flag为true的时候才执行方法体,进行打印输出。(4)join()方法: 参考这篇博文。(3)线程礼让yield()方法。礼让不一定成功,得看cpu的心情。创建,就绪,运行,阻塞,死亡。...原创 2022-08-26 13:59:38 · 131 阅读 · 0 评论 -
线程的join方法:thread.join()
假设总共有thread1,thread2,thread3三个线程(当然加上主线程就是四个线程)thread1被主线程调用thread1.join()thread1.join()会使得主线程(即调用thread1.join()的线程)阻塞,进入等待池,但是并不会影响此时其他处在运行状态的线程thread2和thread3,等thread1执行完毕,主线程才会被唤醒......原创 2022-06-21 10:04:56 · 300 阅读 · 0 评论 -
java线程同步
如果多个线程同时读写共享变量,会出现数据不一致的问题1.一个现象:在主线程中再新开两个线程,这两个线程都是用来对静态变量count进行修改,一个线程add用来对count变量进行加操作,加10000次,另一个线程dec用来对count变量进行减操作,减10000次按理说,加一万次,减一万次,最后结果应该是0,但是,实际运行起来发现每次结果都不一样:2. 原子操作对于一条语句:假设n=100,然后两个线程同时执行n=n+1,最后得到的结果很可能不是102,而是101,这是因为:n=n+1实际上是对应了三原创 2022-06-21 10:44:31 · 121 阅读 · 1 评论 -
第一篇文章:多线程基础
1.交替执行还是一直占有cpu?多个任务轮流获得cpu的使用权,比如让浏览器执行0.001秒,让QQ执行0.001秒,再让音乐播放器执行0.001秒虽然实际上是轮流地(即某一个时刻只能有一个任务使用cpu)但是,由于一个任务失去cpu使用权之后只需等待很短地一段时间就又会再次获得cpu使用权,所以在外人看来,好像这个任务在一直拥有cpu的使用权2.进程和线程一个任务就是一个进程,浏览器就是一个进程,视频播放器是另一个进程,音乐播放器和Word也是进程某些进程内部还需要同时执行多个子任务。例如,我们在使用Wo原创 2022-06-21 10:45:11 · 162 阅读 · 0 评论