Java学习 --- JUC线程通信

目录

一、线程通信使用synchronized实现

 二、基于lock接口实现


一、线程通信使用synchronized实现

案例:使用两个线程,实现对一个初始值是0的变量操作,一个线程对其进行加一操作,另一个线程对其进行减一操作,这个过程就是线程通信。

三步骤:判断、干活、通知

参考示例代码:

public class ThreadDemo01 {
    public static void main(String[] args) {
        //创建对象
        Share share = new Share();
        //创建线程
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"aa").start();
        //创建线程
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"bb").start();
    }
}
/**
 * 创建资源类
 */
class Share{
    private int number = 0;
    //加的方法
    public synchronized void  incr() throws InterruptedException {
        //判断number是否为零,不是零就等待
        if (number != 0){
            this.wait();
        }
        //不为零就加一
        number++;
        System.out.println(Thread.currentThread().getName()+"::"+number);
        //通知其他线程
        this.notifyAll();
    }
    //减的方法
    public synchronized void  decr() throws InterruptedException {
       //判断number是否为一,不是一就等待
        if (number != 1){
            this.wait();
        }
        //不为零就加一
        number--;
        System.out.println(Thread.currentThread().getName()+"::"+number);
        //通知其他线程
        this.notifyAll();
    }
}

 上面的代码存在虚假唤醒

示例代码:

public class ThreadDemo01 {
    public static void main(String[] args) {
        //创建对象
        Share share = new Share();
        //创建线程
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"aa").start();
        //创建线程
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"bb").start();
        //创建线程
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"cc").start();
        //创建线程
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"dd").start();
    }
}
/**
 * 创建资源类
 */
class Share{
    private int number = 0;
    //加的方法
    public synchronized void  incr() throws InterruptedException {
        //判断number是否为零,不是零就等待
        if (number != 0){
            this.wait();
        }
        //不为零就加一
        number++;
        System.out.println(Thread.currentThread().getName()+"::"+number);
        //通知其他线程
        this.notifyAll();
    }
    //减的方法
    public synchronized void  decr() throws InterruptedException {
        //判断number是否为一,不是一就等待
        if (number != 1){
            this.wait();
        }
        //不为零就加一
        number--;
        System.out.println(Thread.currentThread().getName()+"::"+number);
        //通知其他线程
        this.notifyAll();
    }
}

运行结果:

 

原因是wait方法引起的:

 由于wait方法的特点就是在那里睡就在那里醒,会导致if判断条件失效。

解决方法将if判断修改为while循环

参考示例代码:

public class ThreadDemo01 {
    public static void main(String[] args) {
        //创建对象
        Share share = new Share();
        //创建线程
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"aa").start();
        //创建线程
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"bb").start();
        //创建线程
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"cc").start();
        //创建线程
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"dd").start();
    }
}
/**
 * 创建资源类
 */
class Share{
    private int number = 0;
    //加的方法
    public synchronized void  incr() throws InterruptedException {
        //判断number是否为零,不是零就等待
        while (number != 0){
            this.wait();
        }
        //不为零就加一
        number++;
        System.out.println(Thread.currentThread().getName()+"::"+number);
        //通知其他线程
        this.notifyAll();
    }
    //减的方法
    public synchronized void  decr() throws InterruptedException {
       //判断number是否为一,不是一就等待
        while (number != 1){
            this.wait();
        }
        //不为零就加一
        number--;
        System.out.println(Thread.currentThread().getName()+"::"+number);
        //通知其他线程
        this.notifyAll();
    }
}

正确运行结果:

 

 二、基于lock接口实现

public class ThreadDemo2 {
    public static void main(String[] args) {
        Share share = new Share();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"aa").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"bb").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"cc").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"dd").start();
    }
}
class Share{
    private int number = 0;
    //创建lock对象
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    //加
    public void incr() throws InterruptedException {
        //上锁
        lock.lock();
        try {
           while (number != 0){
               condition.await();
           }
           //加一
           number++;
            System.out.println(Thread.currentThread().getName()+"::"+number);
            condition.signalAll();
        }finally {
            //解锁
            lock.unlock();
        }
    }
    //减
    public void decr() throws InterruptedException {
        //上锁
        lock.lock();
        try {
            while (number != 1){
                condition.await();
            }
            //加一
            number--;
            System.out.println(Thread.currentThread().getName()+"::"+number);
            condition.signalAll();
        }finally {
            //解锁
            lock.unlock();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸭鸭老板

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值