您当前的位置: 首页 >  Java

小志的博客

暂无认证

  • 2浏览

    0关注

    1217博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java并发多线程编程——线程之间的通信之wait()、 notify()、notifyAll()

小志的博客 发布时间:2021-05-19 22:19:16 ,浏览量:2

目录
    • 一、volatile 关键字来实现线程间相互通信示例
    • 二、Object类的wait()和 notify()方法来实现线程间相互通信示例
    • 三、Object类的wait()方法让当前线程进入等待状态,并且释放对象的锁示例
    • 四、Object类的notify()方法随机唤醒所有等待线程中的某一线程示例
    • 五、Object类的notifyAll方法唤醒所有等待的线程示例

一、volatile 关键字来实现线程间相互通信示例

1、代码示例

package com.xz.thread.t13;

/**
 * @description: 基于 volatile 关键字来实现线程间相互通信
 *               多个线程同时监听一个变量,当这个变量发生变化的时候 ,
 *               线程能够感知并执行相应的业务
 * @author: xz
 * @create: 2021-05-18 22:20
 */
public class Demo1 {
    //定义一个共享变量signal来实现通信,它需要是volatile修饰,否则线程不能及时感知
    private volatile int signal;//信号

    //获取共享变量signal的方法
    public int getSignal() {
        return signal;
    }
	//修改共享变量signal的方法
    public void setSignal(int signal) {
        this.signal = signal;
    }

    public static void main(String[] args) {
        Demo1 demo1=new Demo1();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"修改线程状态开始");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                demo1.setSignal(1);//设置共享变量signal的值为1
                System.out.println(Thread.currentThread().getName()+"修改线程状态结束");
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(demo1.getSignal() !=1){//signal!=1,什么都不执行
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //当signal==1的时候开始执行
                System.out.println(Thread.currentThread().getName()+"执行代码。。。。");
            }
        }).start();
    }
}

2、运行main函数,输出截图如下:

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

二、Object类的wait()和 notify()方法来实现线程间相互通信示例
  • 注:wait()和 notify()方法必须放在同步代码块或者同步方法中使用

1、代码示例

package com.xz.thread.t13;

/**
 * @description:  Object类的wait()和 notify()方法来实现线程间相互通信
 *                wait()和 notify()方法必须放在同步代码块或者同步方法中使用
 * @author: xz
 * @create: 2021-05-18 22:30
 */
public class Demo2 {
    //定义一个共享变量signal来实现通信,它需要是volatile修饰,否则线程不能及时感知
    private volatile int signal;//信号

    //获取共享变量signal的方法
    public int getSignal() {
        return signal;
    }
    //修改共享变量signal的方法
    public void setSignal(int signal) {
        this.signal = signal;
    }

    public static void main(String[] args) {
        Demo2 demo2=new Demo2();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (demo2){
                    System.out.println(Thread.currentThread().getName()+"修改线程状态开始");
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    demo2.setSignal(1);
                    System.out.println(Thread.currentThread().getName()+"修改线程状态结束");
                    demo2.notify();//notify()方法必须放在同步代码块或者同步方法中使用
                }

            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (demo2){
                    while(demo2.getSignal() !=1){//signal!=1,所以什么都不执行
                        try {
                            demo2.wait();//wait()必须放在同步代码块或者同步方法中使用
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    //当signal==1的时候开始执行
                    System.out.println(Thread.currentThread().getName()+"执行代码。。。。");
                }
            }
        }).start();
    }

}

2、运行main函数,输出截图如下:

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

三、Object类的wait()方法让当前线程进入等待状态,并且释放对象的锁示例

1、代码示例

package com.xz.thread.t13;
public class Demo3 {
    //定义一个共享变量signal来实现通信,它需要是volatile修饰,否则线程不能及时感知
    private volatile int signal;//信号

    //定义一个执行代码的get方法
    public synchronized int get() {
        System.out.println(Thread.currentThread().getName()+"代码执行开始");
       if(signal != 1){
           try {
               wait();
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
        System.out.println(Thread.currentThread().getName()+"代码执行结束");
       return signal;
    }

    public static void main(String[] args) {

        Demo3 demo3 = new Demo3();
        //创建线程任务
        Target2 target2 = new Target2(demo3);

        //开始创建线程
        new Thread(target2).start();
        new Thread(target2).start();
        new Thread(target2).start();
        new Thread(target2).start();

    }
}
package com.xz.thread.t13;
public class Target2 implements Runnable{

    private Demo3 demo3;

    public Target2(Demo3 demo){
        this.demo3 =demo;
    }

    //执行代码
    @Override
    public void run() {
        demo3.get();
    }
}

2、运行main函数,输出截图如下: 在这里插入图片描述 3、结论

  • Object类的wait()方法让当前线程进入等待状态,并且释放对象的锁,所以其他线程才进入了synchronized关键字修饰的get()方法。
四、Object类的notify()方法随机唤醒所有等待线程中的某一线程示例

1、代码示例

package com.xz.thread.t13;
/**
 * @author: xz
 * @create: 2021-05-18 22:51
 */
public class Demo3 {
    //定义一个共享变量signal来实现通信,它需要是volatile修饰,否则线程不能及时感知
    private volatile int signal;//信号

    //定义一个修改线程状态的set方法
    public synchronized void set() {
        signal=1;
        notify();//调用notify()方法,随机唤醒所有等待线程中的某一线程
    }

    //定义一个执行代码的get方法
    public synchronized int get() {
        System.out.println(Thread.currentThread().getName()+"代码执行开始");
       if(signal != 1){
           try {
               wait();//调用wait()方法
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
        System.out.println(Thread.currentThread().getName()+"代码执行结束");
       return signal;
    }

    public static void main(String[] args) {

        Demo3 demo3 = new Demo3();
        //分别创建两个线程任务
        Target1 target1 = new Target1(demo3);
        Target2 target2 = new Target2(demo3);

        //开始4个线程,target2中调用get方法中的wait()
        new Thread(target2).start();
        new Thread(target2).start();
        new Thread(target2).start();
        new Thread(target2).start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //开始1个线程,target1中调用set方法中的notify()
        new Thread(target1).start();
    }
}

package com.xz.thread.t13;
/**
 * @description:
 * @author: xz
 * @create: 2021-05-18 23:00
 */
public class Target1 implements Runnable{
    private Demo3 demo3;

    public Target1(Demo3 demo){
        this.demo3 =demo;
    }

    //修改线程状态
    @Override
    public void run() {
        demo3.set();
    }
}

package com.xz.thread.t13;

/**
 * @description:
 * @author: xz
 * @create: 2021-05-18 23:01
 */
public class Target2 implements Runnable{

    private Demo3 demo3;

    public Target2(Demo3 demo){
        this.demo3 =demo;
    }

    //执行代码
    @Override
    public void run() {
        demo3.get();
    }
}

2、运行main函数,输出截图如下: 在这里插入图片描述 在这里插入图片描述 3、结论

  • 由第2步骤的输出结果截图可知,Object类的notify()方法随机唤醒所有等待线程中的某一线程;
  • 第一张截图唤醒了Thread-2;第二张截图唤醒了Thread-0;
五、Object类的notifyAll方法唤醒所有等待的线程示例

1、代码示例

package com.xz.thread.t13;
/**
 * @author: xz
 * @create: 2021-05-18 22:51
 */
public class Demo3 {
    //定义一个共享变量signal来实现通信,它需要是volatile修饰,否则线程不能及时感知
    private volatile int signal;//信号

    //定义一个修改线程状态的set方法
    public synchronized void set() {
        signal=1;
        notifyAll();//调用notifyAll()方法,唤醒所有等待的线程
    }

    //定义一个执行代码的get方法
    public synchronized int get() {
        System.out.println(Thread.currentThread().getName()+"代码执行开始");
       if(signal != 1){
           try {
               wait();//调用wait()方法
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
        System.out.println(Thread.currentThread().getName()+"代码执行结束");
       return signal;
    }

    public static void main(String[] args) {

        Demo3 demo3 = new Demo3();
        //分别创建两个线程任务
        Target1 target1 = new Target1(demo3);
        Target2 target2 = new Target2(demo3);

        //开始4个线程,target2中调用get方法中的wait()
        new Thread(target2).start();
        new Thread(target2).start();
        new Thread(target2).start();
        new Thread(target2).start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //开始1个线程,target1中调用set方法中的notifyAll()
        new Thread(target1).start();
    }
}

package com.xz.thread.t13;

/**
 * @description:
 * @author: xz
 * @create: 2021-05-18 23:00
 */
public class Target1 implements Runnable{
    private Demo3 demo3;

    public Target1(Demo3 demo){
        this.demo3 =demo;
    }

    //修改线程状态
    @Override
    public void run() {
        demo3.set();
    }
}

package com.xz.thread.t13;

/**
 * @description:
 * @author: xz
 * @create: 2021-05-18 23:01
 */
public class Target2 implements Runnable{

    private Demo3 demo3;

    public Target2(Demo3 demo){
        this.demo3 =demo;
    }

    //执行代码
    @Override
    public void run() {
        demo3.get();
    }
}

2、运行main函数,输出截图如下: 在这里插入图片描述

3、结论

  • 由第2步骤的输出结果截图可知,Object类的notifyAll()方法唤醒所有等待的线程,争夺到时间片的线程只有一个;
关注
打赏
1661269038
查看更多评论
立即登录/注册

微信扫码登录

0.2227s