JUC相关

 

 

AQS(AbstractQueuedSynchronizer) :AQS 核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒 时锁分配的机制,这个机制 AQS 是用 FIFO队列锁实现的,即将暂时获取不到锁的线程加入到队列中。下面的ReentrantLock(独占模式),Semaphore(共享模式)等都是继承AQS,AQS内部已经实现好了对FIFO等待队列的逻辑,只需要不同子类实现具体的尝试和释放逻辑即可。对于队列的操作都由AQS完成

独占模式:比如ReentrantLock的Lock方法,调用的就是AQS的tryAcquire(),这个方法是独占的,只能有一个线程执行返回成功

共享模式:比如Semaphore的acquire(),调用的AQS的tryAcquireShared()方法,在Semaphore初始变量没有变为0之前,都可以获取成功

这里说一点:ReentrantLock获取的condition.await()方法,会释放当前线程获取的锁,然后LockSupport.Park

 

1.CountDownLatch (减法计数器)

底层:利用LockSupport.park,挂起await线程。每个countDown会cas+自旋操作释放一个计数器,直到计数器为0,调用LockSupport.unPark来唤醒线程

 

 

 

2.CyclicBarrier(加法计数器)

底层:利用reentrantLock实现并发控制,condition实现唤醒,每个线程进来后对构造函数设置的容量减-,然后当前线程利用condition.await睡眠,当容量为0时,condition.singleAll来唤醒所有线程(这样使用condition跟object.await没啥区别)

 

 

 

 

 

 

3.Semaphore(信号量)

底层:非公平:进来先尝试cas+自旋操作对初始容量进行减1,直到容量被减完,当前线程加入排队队列,然后LockSupport.Park

公平:进来若发现队列有线程在等着排队减1,则加入队列,然后LockSupport.park。否则直接尝试CAS减1,失败则自旋再重复此操作。

释放:每个线程释放时LockSupport.unPark唤醒下一个线程

 

 

 

 

 

 

 

 

4.读写锁

 

 

 

结论:在读写锁中。若有写锁,则读锁获取失败。有读锁时,写锁获取失败。

跟Synchronized区别就是 这种锁支持多线程 写写互斥,读写互斥,读读不互斥。而如果给读写2个方法都加Synchronized,那就永远只有一个线程可以获取锁,做不到读读不互斥。

摘自百度百科

 

 

 

5.BlockingQueue(阻塞队列)

 

 

 

6.SynchronizedQueue(同步队列)

只能put(o)一个值进去,必须take()取走后,才能重新put下一个值进去。 而且put,take都是阻塞方法,必须2个线程才能操作。相当于

A线程put完会一直阻塞,直到其他线程值被取走,A线程才会继续执行,否则代码就卡在put()方法处。

B线程take()会一直阻塞,直到有值进入队列,B线程才会继续执行,否则代码就卡在take()方法处。

这个跟ArrayBlcokingQueue不同,ArrayBlcokingQueue的put()方法,只有队列长度超过设置的初始值,才会阻塞。就算new ArrayBlcokingQueue(1),也是在put第二个值才会阻塞。take同理

这个SynchronizedQueue是调用put就会立马阻塞,必须其他线程去取。

 

这2块代码都不会输出  111;

 

 

 

7.异步回调  Completable方法详解

runAsync(无返回值)

 

 supplyAsync(有返回值的异步)

 

 

handle 和 thenApply 区别:上个异步若返回异常,thenApply无法触发,handle可以触发并且自定义处理异常

 thenApply(在某个异步执行后 执行指定异步,注意:若上个异步发生异常,则无法执行

 

handleAsync(在某个异步执行后 执行指定异步,注意:可以捕获上一个异步的异常消息

 

posted @ 2021-09-27 21:27  来自China的神秘人  阅读(33)  评论(0)    收藏  举报