JUC的学习与应用(是对文章的补充)

sleep和wait的区别

(两者都须要捕捉异样,这个异样不是重点)

1、每个对象都有一个锁来管制同步拜访,Synchronized关键字能够和对象的锁交互,来实现同步办法或同步块。sleep()办法正在执行的线程被动让出CPU(而后CPU就能够去执行其余工作),在sleep指定工夫后CPU再回到该线程持续往下执行(留神:sleep办法只让出了CPU,而并不会开释同步资源锁!!!);wait()办法则是指以后线程让本人临时让步出同步资源锁,以便其余正在期待该资源的线程失去该资源进而运行,只有调用了notify()办法,之前调用wait()的线程才会解除wait状态,能够去参加竞争同步资源锁,进而失去执行。(留神:notify的作用相当于叫醒睡着的人,而并不会给他分配任务,就是说notify只是让之前调用wait的线程有权力从新参加线程的调度);

2、sleep()办法能够在任何中央应用;wait()办法则只能在同步办法或同步块中应用(否则执行的时候就会报错java.lang.IllegalMonitorStateException)详情能够参考这个博客;

3、sleep()是线程线程类(Thread)的办法,调用会暂停此线程指定的工夫,但监控仍然放弃,不会开释对象锁,到工夫主动复原;wait()是Object的办法,调用会放弃对象锁,进入期待队列,待调用notify()/notifyAll()唤醒指定的线程或者所有线程,才会进入锁池,不再次取得对象锁才会进入运行状态;

synchronized 和 lock

lock锁的几种机制

上面举例具体阐明这四种办法的应用:如果线程A和线程B应用同一个锁LOCK,此时线程A首先获取到锁LOCK.lock(),并且始终持有不开释。如果此时B要去获取锁,有四种形式:

①LOCK.lock(): 此形式会始终处于期待中,即便调用B.interrupt()也不能中断,除非线程A调用LOCK.unlock()开释锁。②LOCK.lockInterruptibly(): 此形式会期待,但当调用B.interrupt()会被中断期待,并抛出InterruptedException异样,否则会与lock()一样始终处于期待中,直到线程A开释锁。

③LOCK.tryLock(): 该处不会期待,获取不到锁并间接返回false,去执行上面的逻辑。

④LOCK.tryLock(10, TimeUnit.SECONDS):该处会在10秒工夫内处于期待中,但当调用B.interrupt()会被中断期待,并抛出InterruptedException。10秒工夫内如果线程A开释锁,会获取到锁并返回true,否则10秒过后会获取不到锁并返回false,去执行上面的逻辑。

两者比照

  1. Synchronized 内置的Java关键字, Lock 是一个Java类
  2. Synchronized 无奈判断获取锁的状态,Lock 能够判断是否获取到了锁
  3. Synchronized 会主动开释锁,lock 必须要手动开释锁!如果不开释锁,死锁
  4. Synchronized 线程 1(取得锁,阻塞)、线程2(期待,傻傻的等);Lock锁就不肯定会期待下
    去;
  5. Synchronized 可重入锁,不能够中断的,非偏心;Lock ,可重入锁,能够 判断锁,非偏心(能够
    本人设置);
  6. Synchronized 适宜锁大量的代码同步问题,Lock 适宜锁大量的同步代码!

生产者消费者问题

传统wait和notify带来的虚伪唤醒问题

参考虚伪唤醒,也就是说在while中,被唤醒的时候是从wait的中央开始,这样就会再做一次判断,而if就间接走上面的逻辑,不会二次判断。参考案例

汇合类线程平安

线程安全类有两种计划,一种是应用Collections.synchronizedxxx()办法,一种是应用比方CopyOnWriteList,这两种适宜不同的场景,具体能够参考这两个

1.List汇合

CopyOnWriteArrayList 实现原理

2.set汇合

阻塞队列

形式抛出异样有返回值,不抛出异样阻塞期待超时期待
增加addoffer()put()offer(,,)
移除removepoll()tack()poll(,,)
查看队首元素elementpeak()--

四组api中,其中第三组中,阻塞的时候 task,poll,remove是都能够取出数据而后再put的。

SynchronousQueue (狂的演示代码不能阐明问题,因为每次都是线程期待)如果始终put的话,的确队列中只能存在一个值,只有被取出才能够再放。参考

线程池

  • 1、2示意外围线程数
  • 当候客区满了之后就是启动3、4、5的最大线程数
  • 此时如果还是满的就是触发回绝策略
  • 当线程完结,3、4、5闲暇工夫达到设置的值后就会主动回收

JMM

小狂笔记中的store 和 write写反了。

单例模式

懒汉式中的dubble check 还要volitaile,避免在两次检测后进行new 的时候呈现指令重排,导致对象还没有实例化实现。一般的单例模式能够通过反射被破解。

原子援用

应用包装类可能会呈现问题,失常的业务逻辑应该是不同的java类。因为在进行compare的时候应用的是==来判断的。