高并发(6)- 多线程之间的协作

2020-03-30  本文已影响0人  残冬十九

@[TOC](高并发(6)- 多线程之间的协作)

前言

    上篇文章讲解了线程之间的共享。本篇文章就来讲讲线程之间的协作。
    毕竟java线程是协作式,而非抢占式的。

线程的协作

一、什么是线程的协作
  顾名思义,线程的协作就是多个线程之间的协作。比如快递这个场景,一个线程负责处理快递的物流信息更新,什么时候快递到了什么的地区,一个线程负责快递的事实信息,当快递到了某个地点,这个时候通知负责物流更新的线程物流进度有变化,你快更新,这个就是线程的协作。
二、线程协作方式
  wait、notify、notifyAll三种方法来实现,分别是等待,唤醒和全部唤醒方法。
1.waiti
  wait是等待方法,执行wait方法会释放当前锁,让出cpu,进入等待状态。只要notify/notifyAll()方法被执行的时候,才会唤醒一个或多个正处于等待的线程,然后继续往下执行,执行完synchronized 代码块的或者遇到了wait的时候,会再次释放锁。 
2.notify
  notify是唤醒方法,可以唤醒当前线程,从wait状态回到就绪状态,重新参与cpu的抢夺之中。
3.notifyAll
  notifyAll也是唤醒方法,但唤醒的是所有线程,使所有的wait状态的线程重新回到就到就绪状态,同样参与cpu的争夺。
三、代码

/**
 * @version 1.0
 * @Description 快递对象
 * @Author wb.yang
 */
public class Express {


    public final static String CITY = "HeNan";
    /**
     * 快递地址
     */
    private String site;

    public Express(String site) {
        this.site = site;
    }


    /**
     * 地点数有变化的时候,通知处于wait状态的,进行公里变化的业务处理
     */
    public synchronized void changeSite() {
        this.site = "BeiJing";
        notifyAll();
    }

    public synchronized void waitSite() {
        while (CITY.equals(this.site)) {
            try {
                System.out.println("检查地点线程[" + Thread.currentThread().getId()
                        + "] 等待中");
                wait();
                System.out.println("检查地点线程[" + Thread.currentThread().getId()
                        + "] 被通知了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("当前地点是" + this.site + "我要通知用户");
    }
}

上面的代码可以看出,我们定义了一个快递的对象,包含了快递当前地点,还有一个等待地点变化的方法,在本方法中等待地点变化,实行我们的业务逻辑,然后有一个变化地点的方法,变换快递地点并调用notifyAll方法,唤醒等待的线程。

/**
 * @version 1.0
 * @Description 线程协作demo
 * @Author wb.yang
 */
public class SynergyDemo {

    private static Express express = new Express(Express.CITY);


    private static class CheckSite extends Thread {
        @Override
        public void run() {
            express.waitSite();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new CheckSite().start();
        Thread.sleep(5000);
        //快递地点更新
        System.out.println("快递地点更新");
        express.changeSite();
    }
}

这个代码是我们执行线程的方法,main方法中,先运行了线程的run方法,进行快递地点变化的等待,然后休眠五秒后,调用快递地点变化的方法,唤醒等待的线程,执行接下来物流更新的逻辑。


代码运行结果

从结果中可以看出,先是线程检查地点,然后进入等待中,随后开始更新快递地点,然后线程结束等待,输出最新的物流信息。
四、总结
  通过使用wait方法使线程进入等待状态,然后释放锁,让出cpu,通过notify和notifyAll来唤醒线程,是等待状态重新变为就绪状态,开始抢夺cpu,然后执行业务逻辑。

上一篇下一篇

猜你喜欢

热点阅读