【JAVA全栈 线程的通信 THREAD】

线程通信

通过加锁的方式保证共享数据访问的完整性,但是并没有规定线程执行的先后顺序。至于,各线程到底谁先执行由操作系统的调度所决定
在进行多线程程序设计时,还会遇到另一类问题**:如何控制相互交互的线程之间的运行顺序,即多线程间的同步。**

API常用方法

Java通过Object类的wait、nofify、notifyAll方法实现线程间的通信。由于锁可以是任意对象,所以这些方法都定义在Object类中。

wait( )
使当前线程放弃同步锁并进入到等待,直到其它线程进入此同步锁并调用notify()或notifyAll()方法唤醒该线程为止

notify( )
唤醒此同步锁上等待的第一个调用wait()方法的线程。

notifyAll( )
唤醒此同步锁上调用wait( )方法的所有线程

注意
**wait( )、 notify( )、notifyAll( )**这三个方法的调用者都应该是同步锁对象;否则JVM抛出IllegalMonitorStateException异常。

此处为接口实现类 以及 重写的run方法:
synchronized(同步) 是wait(等待) 和 notify(通知) 能使是数据同步的关键

Thread01(t1) and Thread02(t2) Running together one by one wait and notify
t1 wait ----->running ----->finished------->notify--------->wait
t2 --------->t2 notify ------>wait ------->back running ->finished

package com.etime809;

import java.util.concurrent.locks.ReentrantLock;

public class RunnableImpl01 implements Runnable {
    private int number = 1;
    private ReentrantLock reentrantLock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            /**
             * synchronized 是wait 和 notify 能使是数据同步的关键
             * Thread01(t1) and Thread02(t2) Running together one by one wait and notify
             *
             * t1 wait ----->running ----->finished------->notify--------->wait
             * t2 --------->t2 notify ------>wait  ------->back running ->finished
             */
            synchronized (reentrantLock) {
                reentrantLock.notify();
                if (number <= 100) {
                    String name = Thread.currentThread().getName();
                    System.out.println(name + "当前线程正在打印:" + number++);
                    try {
                        reentrantLock.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    break;
                }
            }
        }
    }
}

此处为main函数测试文件

package com.etime809;

public class RunnableTest01 {
    public static void main(String[] args) {
        RunnableImpl01 runnableImpl01 = new RunnableImpl01();
        Thread t1  = new Thread(runnableImpl01,"线程①");
        Thread t2  = new Thread(runnableImpl01,"线程②");
        Thread t3  = new Thread(runnableImpl01,"线程③");
        Thread t4  = new Thread(runnableImpl01,"线程④");
        Thread t5  = new Thread(runnableImpl01,"线程⑤");

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();

    }
}

小 结
1、 调用wait()进入阻塞状态并且释放锁
2、 调用notify()唤醒阻塞的线程
3、 流程与理解:线程1打印数字后执行lock.wait()方法线程1进入阻塞状态并释放锁;线程2进入run方法后调用notify()唤醒阻塞的线程1,线程1继续执行直至完成;当线程2打印数字后执行lock.wait()方法线程2进入阻塞状态并释放锁…依次类推
4、 锁、锁.wait()、锁.nofity()这三处必须是同一个锁(监视器)

案例(Producer && Consumer && Test && BankCard)

这是一个比较简单的wait() 和notify() 的例子 帮助我们更好的理解线程通信的应用

package com.etime809;

/**
 * 银行卡类
 * BankCard
 */
public class BankCard {
    private String number;
    private double money;
    private String message;

    public BankCard() {
    }

    public BankCard(String number, double money, String message) {
        this.number = number;
        this.money = money;
        this.message = message;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

package com.etime809;

/**
 * 消费者 Consumer Runnable实现类
 */
public class ConsumerRunnable implements Runnable {
    private BankCard bankCard;

    public ConsumerRunnable() {
    }

    public ConsumerRunnable(BankCard bankCard) {
        this.bankCard = bankCard;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (bankCard) {
                if (bankCard.getMoney() > 0) {
                    String message = bankCard.getMessage();
                    System.out.println(message + "取了:" + bankCard.getMoney());
                    bankCard.setMoney(0);
                    bankCard.notify();
                } else {
                    try {
                        bankCard.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

package com.etime809;

/**
 * 生产者producer  runnable 实现类
 */
public class ProducerRunnable implements Runnable {
    private int counter = 0;
    private BankCard bankCard;

    public ProducerRunnable() {
    }

    public ProducerRunnable(BankCard bankCard) {
        this.bankCard = bankCard;
    }

    @Override
    public void run() {
        while (true) {

            synchronized (bankCard) {
                if (bankCard.getMoney() <= 0) {
                    if (counter % 2 == 0) {
                        bankCard.setMessage("父亲给你打钱了!");
                        bankCard.setMoney(2000);
                    } else {
                        bankCard.setMessage("母亲给你打钱了!");
                        bankCard.setMoney(4000);
                    }
                    counter++;
                    bankCard.notify();
                } else {
                    try {
                        bankCard.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

package com.etime809;

public class ProducerConsumerTest {
    public static void main(String[] args) {
        BankCard bankCard = new BankCard("666666", 10, "开户成功!");

        ProducerRunnable producerRunnable = new ProducerRunnable(bankCard);
        ConsumerRunnable consumerRunnable = new ConsumerRunnable(bankCard);

        Thread t1 = new Thread(producerRunnable);
        Thread t2 = new Thread(consumerRunnable);
        t1.start();
        t2.start();
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值