高内聚低耦合通俗理解_JUC并发编程之轻松学会Lokc锁,深入理解lock锁与Synchronized区别...

学习预告:本节课只是概要,通过本次课程需要掌握学会使用Lock锁,理解lock锁与Synchronized区别,以及在Synchronized版本和LoKC下消费者和生产者!

3、Lock锁 

学会使用Lock锁(温馨提示:先看完视频,然后再进行去看代码,进行练习实操哦)

传统同步

package com.coding.demo01;import java.util.TimerTask;/*** 卖票 自己会写 3个售票员卖出30张票使用 juc.locks 包下的类操作 Lock 锁 + Lambda 表达式* 企业中禁止这样写,Coding:企业级开发!** 多线程编程的固定套路:* 1、高内聚,低耦合 (前提)* 2、线程 操作(调用对外暴露的方法) 资源类 (要点)*/public class SaleTicketTest1 {public static void main(String[] args) {// 资源类final SaleTicket saleTicket = new SaleTicket();new Thread(new Runnable() {public void run() {for (int i = 1; i < 40; i++) {saleTicket.saleTicket();}}}, "A").start();new Thread(new Runnable() {public void run() {for (int i = 1; i < 40; i++) {saleTicket.saleTicket();}}}, "B").start();new Thread(new Runnable() {public void run() {for (int i = 1; i < 40; i++) {saleTicket.saleTicket();}}}, "C").start();}}// 属性,和方法 高内聚class SaleTicket{ //资源类private int number = 30;// 卖票方法public synchronized void saleTicket(){if (number>0){System.out.println(Thread.currentThread().getName()+"卖出第"+(number--) +"还剩下:"+number+"张票");}}}

使用 juc.locks 包下的类操作 Lock 锁 + Lambda 表达式 

0a8bb7b57bc4b1373e5cc40852ab6eb0.png

03db6a72acfe80d3bd1df877287efe94.png

package com.coding.demo01;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/*** 卖票 自己会写 3个售票员卖出30张票* 企业中禁止这样写,Coding:企业级开发!* * 多线程编程的固定套路:* 1、高内聚,低耦合 (前提)* 2、线程 操作(调用对外暴露的方法) 资源类 (要点)*/public class SaleTicketTest2 {public static void main(String[] args) {// 并发:多线线程操作同一个资源类// 资源类SaleTicket2 saleTicket = new SaleTicket2();// lambda表达式、链式编程、流式计算!// lambda表达式,() -> {} 自动推断类型// IDEA 一定要设置 JDK 版本为 1.8 版本new Thread(() -> {for (int i = 1; i < 40; i++) saleTicket.saleTicket();}, "A").start();new Thread(() -> {for (int i = 1; i < 40; i++) saleTicket.saleTicket();}, "B").start()new Thread(() -> {for (int i = 1; i < 40; i++) saleTicket.saleTicket();}, "C").start();}}// 属性,和方法 高内聚class SaleTicket2 { //资源类private int number = 30;// 锁LOCKprivate Lock lock = new ReentrantLock(); // 可重入// 卖票方法public void saleTicket() {lock.lock(); // 加锁try {// 业务代码if (number > 0) {System.out.println(Thread.currentThread().getName() + "卖出第" +(number--) + "还剩下:" + number + "张票");}} catch (Exception e) {e.printStackTrace();} finally {lock.unlock(); // 解锁}}}

synchronized 和 lock 区别 (自动挡 手动挡)

synchronized 和 lock 区别

1、synchronized 关键字,Java内置的。lock 是一个Java 类

2、synchronized 无法判断是否获取锁、lock 可以判断是否获得锁

3、synchronized 锁会自动释放!lock 需要手动在 fifinally 释放锁,如果不释放锁,就会死锁

4、synchronized 线程1阻塞 线程2永久等待下去。lock可以 lock.tryLock(); // 尝试获取锁,如果尝试获取不到锁,可以结束等待

5、synchronized 可重入,不可中断,非公平的,Lock锁,可重入、可以判断、可以公平! 

4、生产者和消费者(高频)

生产者和消费者 synchroinzed 版  (温馨提示:先看完视频,然后再进行去看代码,进行练习实操哦)

线程间的通信、无法通信,调度线程 

生产者和消费者 synchroinzed 版 

package com.coding.demo02;/*** 题目:现在两个线程,操作一个初始值为0的变量* 一个线程 + 1, 一个线程 -1。判断什么时候+1,什么时候-1* 交替10 次** 方法论:** 多线程编程的固定套路:* 1、高内聚,低耦合 (前提)* 2、线程 操作(调用对外暴露的方法) 资源类 (要点)** 生产者消费者模型:判断、干活、通知*/public class A {public static void main(String[] args) {Data data = new Data();new Thread(()->{for (int i = 1; i <= 10; i++) {try {data.increment();} catch (Exception e) {e.printStackTrace();}}},"A").start();new Thread(()->{for (int i = 1; i <= 10; i++) {try {data.decrement();} catch (Exception e) {e.printStackTrace();}}},"B").start();}}// 资源类 属性,方法class Data{private int num = 0;// +1public synchronized void increment() throws Exception{//判断if (num!=0){this.wait();}// 干活num++;System.out.println(Thread.currentThread().getName()+"\t"+num);// 通知this.notifyAll();}// -1public synchronized void decrement() throws Exception{// 判断if (num==0){this.wait();}// 干活num--;System.out.println(Thread.currentThread().getName()+"\t"+num);// 通知this.notifyAll();}}

问题升级:防止虚假唤醒,4个线程,两个加,两个减 

773380628daa3ad9606b918f8ae38ece.png

package com.coding.demo02;/*** 题目:现在两个线程,操作一个初始值为0的变量* 一个线程 + 1, 一个线程 -1。判断什么时候+1,什么时候-1* 交替10 次** 方法论:** 多线程编程的固定套路:* 1、高内聚,低耦合 (前提)* 2、线程 操作(调用对外暴露的方法) 资源类 (要点)** 生产者消费者模型:判断、干活、通知*/public class A {public static void main(String[] args) {Data data = new Data();new Thread(()->{for (int i = 1; i <= 10; i++) {try {data.increment();} catch (Exception e) {e.printStackTrace();}}},"A").start();new Thread(()->{for (int i = 1; i <= 10; i++) {try {data.decrement();} catch (Exception e) {e.printStackTrace();}}},"B").start();new Thread(()->{for (int i = 1; i <= 10; i++) {try {data.increment();} catch (Exception e) {e.printStackTrace();}}},"C").start();new Thread(()->{for (int i = 1; i <= 10; i++) {try {data.decrement();} catch (Exception e) {e.printStackTrace();}}},"D").start();}}// 资源类 属性,方法class Data{private int num = 0;// +1public synchronized void increment() throws Exception{//判断 if 只判断了一次, 0 1 0 1while (num!=0){this.wait();}// 干活num++;System.out.println(Thread.currentThread().getName()+"\t"+num);// 通知this.notifyAll();}// -1public synchronized void decrement() throws Exception{// 判断while (num==0){this.wait(); //0}// 干活num--;System.out.println(Thread.currentThread().getName()+"\t"+num);// 通知this.notifyAll();}}

传统的,JUC!

新版生产者和消费者写法 

40c76cd2de6c01861208d30c65b11258.png

任何一个新技术的出现,一定不仅仅是换了个马甲

62e25434b305a5b9515d793feed0b616.png

手写生产者消费者问题:100 加分项目! 

package com.coding.demo02;import sun.awt.SunHints;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;// lock版生产者消费者public class B {public static void main(String[] args) {// 新版Data2 data = new Data2();new Thread(()->{for (int i = 1; i <= 10; i++) {try {data.increment();} catch (Exception e) {e.printStackTrace();}}},"A").start();new Thread(()->{for (int i = 1; i <= 10; i++) {try {data.decrement();} catch (Exception e) {e.printStackTrace();}}},"B").start();new Thread(()->{for (int i = 1; i <= 10; i++) {try {data.increment();} catch (Exception e) {e.printStackTrace();}}},"C").start();new Thread(()->{for (int i = 1; i <= 10; i++) {try {data.decrement();} catch (Exception e) {e.printStackTrace();}}},"D").start();}}// 资源类 属性,方法class Data2{private int num = 0;// 定义锁Lock lock = new ReentrantLock();private Condition condition = lock.newCondition();// +1public void increment() throws Exception{// 加锁lock.lock();try {//判断while (num!=0){condition.await(); //等待}// 干活num++;System.out.println(Thread.currentThread().getName()+"\t"+num);// 通知condition.signalAll();} catch (InterruptedException e) {e.printStackTrace();} finally {// 解锁lock.unlock();}}// -1public void decrement() throws Exception{// 加锁lock.lock();try {// 判断while (num==0){condition.await(); //等待}// 干活num--;System.out.println(Thread.currentThread().getName()+"\t"+num);// 通知condition.signalAll();} catch (InterruptedException e) {e.printStackTrace();} finally {// 解锁lock.unlock();}}}

如何精确通知访问!

精确通知顺序访问 Condition 

e99d694cc030be63c41cd48737c1f5c1.png

package com.coding.demo02;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/*** 多个线程启动 A -- B -- C* 三个线程依次打印* A 5次* B 10次* C 15次* 依次循环** 精确通知线程消费*/public class C {public static void main(String[] args) {Data3 data = new Data3();// 线程操作资源类new Thread(()->{for (int i = 1; i <= 10; i++) {data.print5();}},"A").start();new Thread(()->{for (int i = 1; i <= 10; i++) {data.print10();}},"B").start();new Thread(()->{for (int i = 1; i <= 10; i++) {data.print15();}},"C").start();}}// 资源类 属性,方法class Data3{private int num = 1; // A1 B2 C3// 定义锁Lock lock = new ReentrantLock();private Condition condition1 = lock.newCondition(); //3个判断,交替执行 A--B--C--Aprivate Condition condition2 = lock.newCondition(); //3个判断,交替执行 A--B--C--Aprivate Condition condition3 = lock.newCondition(); //3个判断,交替执行 A--B--C--A// 3个方法、作业,合3为1// +1public void print5(){// 加锁lock.lock();try {//判断while (num!=1){condition1.await(); //等待}// 干活for (int i = 1; i <=5 ; i++) {System.out.println(Thread.currentThread().getName()+"\t"+i);}// 第一个线程通知第二个线程,第二个线程通知第三个.... 计数器num=2;// 通知第二个线程干活,指定谁干活condition2.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {// 解锁lock.unlock();}}public void print10() {// 加锁lock.lock();try {//判断while (num!=2){condition2.await(); //等待}// 干活for (int i = 1; i <=10 ; i++) {System.out.println(Thread.currentThread().getName()+"\t"+i);}// 第一个线程通知第二个线程,第二个线程通知第三个.... 计数器num=3;// 通知第二个线程干活,指定谁干活condition3.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {// 解锁lock.unlock();}}public void print15() {// 加锁lock.lock();try {//判断while (num!=3){condition3.await(); //等待}// 干活 = 业务代码for (int i = 1; i <=15 ; i++) {System.out.println(Thread.currentThread().getName()+"\t"+i);}num=1;condition1.signal();} catch (InterruptedException e) {e.printStackTrace();} finally {// 解锁lock.unlock();}}}

大家懂锁的吗?锁的谁! 

下节课预告:会为大家分享JUC并发编程系列课8锁的现象(深入理解锁) 

,欢迎大家关注我们哦

792446cc41d783d4ba54c6adfa972a5e.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值