栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

学习java的第四十天,Lock(锁)、线程通信的学习

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

学习java的第四十天,Lock(锁)、线程通信的学习

一、Lock(锁)
  • 从jdk5.0开始,java提供了更强大的线程同步机制–通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当。
  • java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具,锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象
  • ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁!
package com.Thread.Gaoji;

import java.util.concurrent.locks.ReentrantLock;

//测试锁
public class TestLock {
    public static void main(String[] args) {
        Lock lock = new Lock();
        new Thread(lock).start();

    }

}
class Lock extends Thread{
    int ticketNums = 10;

        //定义Lock锁 ReentrantLock
        private final ReentrantLock lock = new ReentrantLock();
        @Override
        public void run () {
        while (true) {
            try {
            lock.lock();
            if (ticketNums > 0) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(ticketNums--);
            } else {
                break;
            }

        }finally{
            //解锁
                lock.unlock();
        }
    }
    }
}

结果图:

synchronized与Lock的对比
  • Lock是显式锁(手动开启和关闭锁,别忘记关闭锁)synchronized是隐式锁,出了作用域自动释放
  • Lock只有代码块锁,synchronized有代码块锁和方法锁
  • 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类)
  • 优先使用顺序:Lock > 同步代码块(已经进入了方法体,分配了相应资源)> 同步方法(在方法体之外)
二、线程通信 应用场景一:生产者和消费者问题
  • 假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费!

  • 如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止!

  • 如果仓库中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中的产品再次放入产品为止!

  • java提供了几个方法解决线程之间的通信问题

方法名作用
wait()表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁
wait(long timeout)指定等待的毫秒数
notify()唤醒一个处于等待状态的线程
notifyAll唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度

注意:均是Object类的方法。都只能在同步方法或者同步代码块中使用,否则会抛出异常IllegalMonitorStrateException。

package com.Thread.Gaoji;
//测试生产者与消费者之间的通信
public class TestPC {
    public static void main(String[] args) {
        SynContainer synContainer = new SynContainer();

        new Productor(synContainer).start();
        new Consumer(synContainer).start();

    }
}

//生产者
class Productor extends Thread{
    SynContainer container;
    public Productor(SynContainer container){
        this.container = container;
    }
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
                container.push(new Chicken(i));
                System.out.println("生产了"+i+"只鸡");
        }
    }
}

//消费者
class Consumer extends Thread{
    SynContainer container;
    public Consumer(SynContainer container){
        this.container = container;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 20; i++) {
                System.out.println("消费了-->"+container.pop().id+"只鸡");
        }
    }
}

//产品
class  Chicken{
    //鸡的编号
    int id;

    public Chicken(int id) {
        this.id = id;
    }
}
//缓冲区
class SynContainer{
    //需要一个容器大小
    Chicken[] chickens = new Chicken[10];
    //容器计数器
    int count = 0;

    //生产者放入产品
    public synchronized void push(Chicken chicken){
        //如果容器满了,就需要等待消费者消费
        if (count==chickens.length){
            //通知消费者消费
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果没有满,我们就需要丢入产品
        chickens[count] = chicken;
        count++;

        //可以通知消费者消费了。
        this.notifyAll();
    }
    //消费者消费产品
    public synchronized Chicken pop(){
        //判断能否消费
        if (count==0){
            //等待生产者生成,消费者等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果可以消费
        count--;
        Chicken chicken = chickens[count];

        //吃完了,通知生产者生产
        this.notifyAll();
        return chicken;
    }
}


结果图

总结:由于我将消费延时了,所以是先生产了10只鸡才开始消费。以此类推!

应用场景二:生产者和消费者问题(信号灯法)
package com.Thread.Gaoji;
//测试表演节目之间的通信
//信号灯法
public class TestTV {
    public static void main(String[] args) {
        Tv tv = new Tv();

        new Player(tv).start();
        new Watcher(tv).start();

    }
}

//生产者--> 演员
class Player extends Thread{
    Tv tv;
    public Player(Tv tv){
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 1; i < 20; i++) {
            if (i%2==0){
                this.tv.play("抖音广告......");
            }else {
                this.tv.play("<仙侠剧>..."+"第"+i+"集");
            }
        }
    }
}

//消费者--> 观众
class Watcher extends Thread{
    Tv tv;
    public Watcher(Tv tv){
        this.tv = tv;
    }

    @Override
    public void run() {

        for (int i = 1; i < 20; i++) {

            this.tv.watch();
        }
    }
}


//产品 -->节目
class Tv{
    //演员表演,观众等待   T
    //观众观看,演员等待   F
    String voice;  //表演的节目 / 观看的节目
    boolean flag = true;

    //表演
    public synchronized void play(String voice){

        if (!flag){  //如果flag为false,也就是观众在观看,则是等待完毕
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("演员开始表演:"+voice);
        //通知观众观看
        this.notifyAll(); //通知唤醒
        this.voice = voice; //保证实时更新
        this.flag = !this.flag;  //如果这里面的flag不等于当前值,则取反!

    }
    //观看
    public synchronized void watch(){
        if (flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("观众观看了:"+voice);
        this.notifyAll();  //通知唤醒
        this.voice = voice; //保证实时更新
        this.flag = !flag;
    }



}

结果图


注:文章仅做个人学习日记,不做学习建议,学习来源:狂神说

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1028258.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号