关于程序员:JUC

33次阅读

共计 2149 个字符,预计需要花费 6 分钟才能阅读完成。

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 的时候应用的是 == 来判断的。

正文完
 0