多线程之间的通信

来源:互联网 发布:软件外包保密协议 编辑:程序博客网 时间:2024/06/02 07:27

一,概述

1.什么时候需要线程间通信?
* 多个线程并发执行时, 在默认情况下CPU是随机切换线程的。
* 如果我们希望线程间有规律的切换, 就需要进行线程间通信。例如先让线程一执行,然后让线程一和线程二轮流交替执行。

2.怎么实现线程间通信?
实现线程间通信要借助于多线程同步,所以也分为两种方法,一种使用synchronized 关键字实现,另一种使用ReentrantLock 类实现。

二,使用synchronized 关键字实现线程间通信

重要点如下:
* 如果希望线程等待, 就调用wait()方法。
* 如果希望唤醒等待的线程, 就调用notify()方法。
* 这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用。
代码示例如下:
首先声明两个成员方法:

int flag = 1;//定义一个标记public void print01(){    synchronized (this){//this称为同步锁对象        if(flag != 1){            try {                this.wait();//调用wait方法,使线程处于等待状态。            } catch (InterruptedException e) {                e.printStackTrace();            }        }        Log.d("kwwl","郭");        Log.d("kwwl","靖");        flag =2;        this.notify();//调用notify方法,唤醒线程    }}    public void print02(){    synchronized (this){        if(flag == 1){            try {                this.wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        Log.d("kwwl","黄");        Log.d("kwwl","蓉");        flag =1;        this.notify();    }}

同时开启两个线程,分别调用print01和print02方法,代码如下:

new Thread(new Runnable() {    public void run() {        while (true) {            print01();        }    }}).start();new Thread(new Runnable() {    public void run() {        while (true) {            print02();        }    }}).start();

在上面print01和print02方法中都使用了synchronized 关键字构成了同步代码块,所以“郭”和“靖”一定同时打印,“黄”和“蓉”一定同时打印。但如果不使用wait方法和notify方法,则会出现“郭靖”打印了很多次才会打印“黄蓉”。而此时使用了wait方法和notify方法,实现了线程间通信功能,则“郭靖”和“黄蓉”轮流交替打印。

说明:this称为同步锁对象,他可以是任意类型的对象,但必须保证两个同步代码块的锁对象是同一个对象。

分析:
假设线程二先执行了,此时判断flag等于1,然后这个线程就会等待,此时线程1就会执行,但线程一执行后flag等于2,并调用notify来唤醒线程,这个方法是随机唤醒使用this锁等待的线程,此时只有线程二处于等待,所以线程二被唤醒。然后若还是线程一执行,那么因为此时flag等于2,所以线程一将被等待,所以就会执行线程二,等等依次执行。

注:如果是三个线程间的通信,可以使用this.notityAll方法,这个方法表示唤醒所有等待的线程。

三,使用ReentrantLock 类实现线程间通信

重要点如下:
*首先创建ReentrantLock 对象,然后再得到Condition 对象。
* 如果希望线程等待, 就调用await()方法。
* 如果希望唤醒等待的线程, 就调用signal()方法。
* 这两个方法必须在同步代码中执行, 并且使用同一个ReentrantLock 对象。
代码示例如下:
首先声明两个成员方法:

int flag = 1;private ReentrantLock lock = new ReentrantLock();Condition c1 = lock.newCondition();Condition c2 = lock.newCondition();public  void print01(){    lock.lock();    if(flag != 1){        try {            c1.await();        } catch (InterruptedException e) {            e.printStackTrace();        }    }    Log.d("kwwl","郭");    Log.d("kwwl","靖");    c2.signal();    lock.unlock();}public  void print02(){    lock.lock();    if(flag != 1){        try {            c2.await();        } catch (InterruptedException e) {            e.printStackTrace();        }    }    Log.d("kwwl","黄");    Log.d("kwwl","蓉");    c1.signal();//唤醒c1    lock.unlock();}

再同时开启两个线程,分别调用两个方法,代码同上。

分析:首先使用ReentrantLock 对象的lock和unlock方法实现了同步代码块。然后又使用Condition类的await方法和signal方法实现了等待唤醒机制,实现了线程间通信。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 oppo手机刷机要锁屏密码怎么办 在苏宁易购退款成功又收到货怎么办 今日头条转发出现未安装微信怎么办 打开手机后自动弹出广告怎么办去除 朋友圈发广告被腾讯屏蔽了怎么办 新商盟手机订烟登录密码忘了怎么办 手机版战神斯巴达幽灵经常崩怎么办 代购买的东西被海关扣了怎么办 托朋友代购给了钱联系不上人怎么办 签了合同被加盟商骗了怎么办 百度云盘下载时本地空间不足怎么办 百度云盘隐私空间没密码忘了怎么办 华为云空间的帐号密码忘记了怎么办 快递被快递公司弄丢了怎么办 快递到了人不在那个地方了怎么办 微信被骗了1千多怎么办 客户货已经用啦要求退款退货怎么办 网购收到别人退货的东西怎么办 好省输入订单编号查不到订单怎么办 快递没有当面验收后发现损坏怎么办 支付宝电脑付款风控异常怎么办 京东买东西地址填错了怎么办 商场卖的衣服跟官网差价大怎么办 网购的衣服有好几个破洞怎么办 出租发票有牌号是假的怎么办 支付宝里的多收多保被降级了怎么办 超市购物卡余额与实际不符怎么办 发广告的公众号无法取消关注怎么办 扣扣需要手机验证码登录怎么办 驾校报了联系不了教练了怎么办 手机号被别人注册了百度网盘怎么办 注册公司云证书申请成功后怎么办 淘宝购物卖家迟迟不发货怎么办 淘宝直播顾客加购物车不下单怎么办 东方航空联程机票航班延误怎么办 别别人伸请更换手机绑定qq怎么办 绑定手机号的扣扣忘记密码怎么办 微信公众号个人主体变更公司怎么办 微信号注册成订阅号了怎么办 微信开通了企鹅影院会员怎么办 注销公众号对公账号填写错误怎么办