前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >多线程笔记(九)线程之间的通信

多线程笔记(九)线程之间的通信

作者头像
一写代码就开心
发布2022-05-25 11:00:22
2800
发布2022-05-25 11:00:22
举报
文章被收录于专栏:java和python

目录

1 虚假唤醒

我们多个线程之间通信,有wait() notify(),notifyall()方法,但是wait()方法是在哪里睡,之后被唤醒的时候就在哪里醒来,所以我们的wait()方法是不能在if里面,使用while,当唤醒的时候,会重新判断条件,if是不会判断的;

2 synchronized之间的通信

wait(),notifyAll(),notify()

代码语言:javascript
复制
//第一步 创建资源类,定义属性和操作方法
class Share {
    //初始值
    private int num = 0;
    //+1的方法
    public synchronized void incr() throws InterruptedException {
        //第二步 判断 干活 通知
       if(number != 0) { //判断number值是否是0,如果不是0,等待
            this.wait(); //在哪里睡,就在哪里醒
        }
        //如果number值是0,就+1操作
        number++;
        System.out.println(Thread.currentThread().getName()+" :: "+num);
        //通知其他线程
        this.notifyAll(); //注意这里的通知是随机的,就是只能通知全部
    }
 
    //-1的方法
    public synchronized void decr() throws InterruptedException {
        //判断
        if(number != 1) {
            this.wait();
        }
        //干活
        number--;
        System.out.println(Thread.currentThread().getName()+" :: "+number);
        //通知其他线程
        this.notifyAll();
    }
}
 
public class ThreadDemo1 {
    //第三步 创建多个线程,调用资源类的操作方法
    public static void main(String[] args) {
        Share share = new Share();
        //创建线程
        new Thread(()->{
            for (int i = 1; i <=10; i++) {
                try {
                    share.incr(); //+1
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"AA").start();
 
        new Thread(()->{
            for (int i = 1; i <=10; i++) {
                try {
                    share.decr(); //-1
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"BB").start();
    }
}

3 lock之间的通信

代码语言:javascript
复制
    private Lock lock= new ReentrantLock();   //创建可重锁
    private Condition  condition= lock.newCondition();
        //他能操作的对象
  • 上锁 lock.lock();
  • 解锁 lock.unlock();
  • 以下都为 condition类: 唤醒所有等待的线程signalAll(),带上类名condition.signalAll(); 唤醒一个等待线程signal(),带上类名,condition.signal(); 造成当前线程在接到信号或者被中断之前一直处于等待状态await(),带上类名,condition.await();
代码语言:javascript
复制
class LShare{
//这是共享资源,注意锁的创建和使用,其他的和上面基本相同
    private int num=0;
 
    private Lock lock= new ReentrantLock();   //创建可重锁
    private Condition  condition= lock.newCondition();
 
    //创建操作的方法
    public void add (){
        lock.lock();   //首先 手动上锁;
        try {  //判断,干活,通知
            while (num!=0){
                condition.await();
                //它使用的是这个对象 调用方法 等待
            }
         num++;
            System.out.println( Thread.currentThread().getName()+" 干活完成 :"+num);
            condition.signalAll(); //这个通知方法
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
           lock.unlock(); //最终不管出现什么错误,都会解锁
        }
    }

4 线程之间的定制化通信

4.1 需求

在这里插入图片描述
在这里插入图片描述

4.2 代码实现

代码语言:javascript
复制
/**定制化通信  ( 规定完成工作量,交替)
 *   AA 打印 5 次 , BB打印10次  CC打印15次
 *   完成10次这样的交替
 *  怎么完成呢?  设置标志位,对应线程, 指定唤醒线程
 *  sysnchronzied 是随机唤醒的, Lock 锁创建Condition 可以指定唤醒
 */
class  ShareRes{
    private int flag =1; // 1 AA,  2 BB ,3 CC
    Lock lock = new ReentrantLock(); //一定记得创建可重锁
 
    Condition c1 =lock.newCondition(); //可以指定唤醒线程
    Condition c2 =lock.newCondition();
    Condition c3 =lock.newCondition();
    //注意唤醒的线程,以及标志位, 和线程的start
 
    //指定AA 做的工作 参数:循环次数
    public void AA(int loop) throws InterruptedException {
        //上锁 ,判断 ,干活,通知,解锁
        lock.lock();
      try {
          while (flag != 1) {
              c1.await();
          }
          for (int i = 1; i <= 5; i++) {
              System.out.println(Thread.currentThread().getName() + " ::" + i + "循环的次数" + loop);
          }
          flag = 2; //修改标志位,定向唤醒 线程b
          c2.signal();
      }finally {
          lock.unlock();
      }
    }
 
    //指定AA 做的工作 参数:循环次数
    public void BB(int loop) throws InterruptedException {
        //上锁 ,判断 ,干活,通知,解锁
        lock.lock();
        try {
            while (flag != 2) {
                c2.await();
            }
            for (int i = 1; i <= 10; i++) {
                System.out.println(Thread.currentThread().getName() + " ::" + i + "循环的次数" + loop);
            }
            flag = 3; //修改标志位,定向唤醒 线程b
            c3.signal();
        }finally {
            lock.unlock();
        }
    }
 
    //指定AA 做的工作 参数:循环次数
    public void CC(int loop) throws InterruptedException {
        //上锁 ,判断 ,干活,通知,解锁
        lock.lock();
        try {
            while (flag != 3) {
                c3.await();
            }
            for (int i = 1; i <= 15; i++) {
                System.out.println(Thread.currentThread().getName() + " ::" + i + "循环的次数" + loop);
            }
            flag = 1; //修改标志位,定向唤醒 线程A
            c1.signal();
        }finally {
            lock.unlock();
        }
    }
}
 
public class c01 {
    public static void main(String[] args) {
        ShareRes shareRes = new ShareRes();
 
        new Thread(   //创建三个线程
                () ->{
                    for (int i = 0; i < 10; i++) {
                        try {
                            shareRes.AA(i);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } } }
       ,"AA" ).start();
        new Thread(
                () ->{
                    for (int i = 0; i < 10; i++) {
                        try {
                            shareRes.BB(i);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } } }
                ,"BB" ).start();
        new Thread(
                () ->{
                    for (int i = 0; i < 10; i++) {
                        try {
                            shareRes.CC(i);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } } }
                ,"CC" ).start();
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 1 虚假唤醒
  • 2 synchronized之间的通信
  • 3 lock之间的通信
  • 4 线程之间的定制化通信
    • 4.1 需求
      • 4.2 代码实现
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档