多线程-----单线程之间的通信wait和notify

一、场景

有若干订单存放到list集合或者队列中,我们不知道什么是满了或者没有订单,

第一种方式:一般会隔固定时间去看list中是否有时间,有了则进行处理,没有则退出,这样一直循环。

第二种方式:就是利用线程之间的通信机制,也就是wait和notify,如果list存放的订单达到了最大限制或者list为空(大小为0),则wait,阻塞线程,否则notify,唤醒线程。

二、wait和notify方法介绍

1、wait和notify不是Thread类独有的,Object类也有,也就是所有类都有这两个方法;

2、第一个方法是没有参数的,源码里面默认为0,也就是永不超时;

public final void wait() throws InterruptedException

public final native void wait(long timeout) throws InterruptedException

public final void wait(long timeout, int nanos) throws InterruptedException
public final void wait() throws InterruptedException {
     wait(0);
}

3、第二个方法和第三个方法都是带有超时时间的,如果超时时间到了,当前线程自动唤醒,或者可以用notify和notifyAlll来唤醒正在阻塞中的线程;

4、调用wait方法对象必须是当前线程持有的锁,否则报java.lang.IllegalMonitorStateException异常,例如:

synchronize(obj){
              
    try {
       obj.wait();
    } catch (InterruptedException e) {
       e.printStackTrace();
    }
}

三、wait和sleep区别:

1、wait是Object中的方法,而sleep是Thread特有的;

2、调用wait时必须持有monitor锁,也是就是必须在同步方法中,而sleep在任何地方都可以调用;

3、调用wait方法之后,线程会释放monitor锁,而sleep不会,直到调用sleep方法的生命周期结束才会释放;

4、wait和sleep都是可中断方法,我们调用这两个方法,必须捕获或者抛出InterruptedException异常(或者它的父类);

5、sleep阻塞到指定时间,会继续执行,而wait(如果没有指定超时时间的情况)需要notify或者notifyAll来唤醒。

四、线程之间通信案例

1、订单类:Order

package com.dl.cn;

/**
 * 订单类
 * Created by Tiger on 2018/8/13.
 */
public class Order {
    public Order(){}
}

2、订单处理类:OrderProcess

package com.dl.cn;


import java.util.LinkedList;

/**
 * Created by Tiger on 2018/8/13.
 */
public class OrderProcess {
    //最大存放订单的数量
    private static final int MAX_ORDER_NUM = 15;
    //存放订单数据
    private static final LinkedList list = new LinkedList();
    /**
     * 添加订单到list
     * */
    public void addOrder(Order order){
        synchronized (list){
            if(list.size() >= MAX_ORDER_NUM){
                try {
                    System.out.println("list("+list.size()+") 已经满了!");
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //将订单添加到list集合
            list.addLast(order);
            System.out.println("订单已提交了!");
            list.notify();
        }
    }
    /**
     * 从list取订单进行处理
     * */
    public void  getOrder(){
        synchronized(list){
            if(list.isEmpty()){
                try {
                    System.out.println("暂时无订单");
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            /**
             * 取出订单,并进行处理,最后移除当前订单
             * */
            Order order = (Order) list.getFirst();
            list.remove(order);
            System.out.println("从list("+list.size()+")取订单成功!");
            list.notify();
        }
    }
}

3、主方法OrderMain

package com.dl.cn;

import java.util.concurrent.TimeUnit;

/**
 * Created by Tiger on 2018/8/13.
 */
public class OrderMain {
    public static void main(String[] args) {
        final OrderProcess orderProcess = new OrderProcess();
        /**
         * 生产
         * */
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        orderProcess.addOrder(new Order());
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        /**
         * 消费
         * */
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        orderProcess.getOrder();
                        TimeUnit.SECONDS.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

ps:这里生产订单每隔1秒执行一次,消费订单每隔2秒执行一次

五、测试结果

E:\jdk18\bin\java -Didea.launcher.port=7535 "-Didea.launcher.bin.path=E:\interllijidea\IntelliJ IDEA\bin" -Dfile.encoding=UTF-8 -classpath "E:\jdk18\jre\lib\charsets.jar;E:\jdk18\jre\lib\deploy.jar;E:\jdk18\jre\lib\ext\access-bridge-64.jar;E:\jdk18\jre\lib\ext\cldrdata.jar;E:\jdk18\jre\lib\ext\dnsns.jar;E:\jdk18\jre\lib\ext\jaccess.jar;E:\jdk18\jre\lib\ext\jfxrt.jar;E:\jdk18\jre\lib\ext\localedata.jar;E:\jdk18\jre\lib\ext\nashorn.jar;E:\jdk18\jre\lib\ext\sunec.jar;E:\jdk18\jre\lib\ext\sunjce_provider.jar;E:\jdk18\jre\lib\ext\sunmscapi.jar;E:\jdk18\jre\lib\ext\sunpkcs11.jar;E:\jdk18\jre\lib\ext\zipfs.jar;E:\jdk18\jre\lib\javaws.jar;E:\jdk18\jre\lib\jce.jar;E:\jdk18\jre\lib\jfr.jar;E:\jdk18\jre\lib\jfxswt.jar;E:\jdk18\jre\lib\jsse.jar;E:\jdk18\jre\lib\management-agent.jar;E:\jdk18\jre\lib\plugin.jar;E:\jdk18\jre\lib\resources.jar;E:\jdk18\jre\lib\rt.jar;F:\ideaWorkSpace\practice\threadDemo\target\classes;E:\interllijidea\IntelliJ IDEA\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.dl.cn.OrderMain
订单已提交了!
从list(0)取订单成功!
订单已提交了!
订单已提交了!
从list(1)取订单成功!
订单已提交了!
订单已提交了!
从list(2)取订单成功!
订单已提交了!
订单已提交了!
从list(3)取订单成功!
订单已提交了!
从list(3)取订单成功!
订单已提交了!
订单已提交了!
从list(4)取订单成功!
订单已提交了!
订单已提交了!
订单已提交了!
从list(6)取订单成功!
订单已提交了!
从list(6)取订单成功!
订单已提交了!
订单已提交了!
从list(7)取订单成功!
订单已提交了!
订单已提交了!
从list(8)取订单成功!
订单已提交了!
订单已提交了!
从list(9)取订单成功!
订单已提交了!
订单已提交了!
从list(10)取订单成功!
订单已提交了!
订单已提交了!
从list(11)取订单成功!
订单已提交了!
订单已提交了!
从list(12)取订单成功!
订单已提交了!
订单已提交了!
从list(13)取订单成功!
订单已提交了!
订单已提交了!
从list(14)取订单成功!
订单已提交了!
list(15) 已经满了!
从list(14)取订单成功!
订单已提交了!
list(15) 已经满了!
从list(14)取订单成功!
订单已提交了!
list(15) 已经满了!
从list(14)取订单成功!
订单已提交了!
list(15) 已经满了!
从list(14)取订单成功!
订单已提交了!

Process finished with exit code -1

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

燕少༒江湖

给我一份鼓励!谢谢!

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

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

打赏作者

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

抵扣说明:

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

余额充值