当前位置: 首页 > news >正文

线程开发之多线程之间的通讯实现

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

线程的概念是什么?线程之间是如何通信的?

       线程是进程中的一个执行单元,同一个进程中的各个线程对应于一组CPU指令、一组CPU寄存器以及一堆栈。进程本来就具有动态的含义,然而实质上是通过线程来执行体现的,从这个意义上说,Windows中进程的动态性意义已经不是很明显了,只算是给程序所占的资源划定一个范围而已,真正具有动态性意义的是线程。

       其实,Java提供了3个非常重要的方法来巧妙地解决线程间的通信问题。这3个方法分别是:wait()、notify()和notifyAll()。它们都是Object类的最终方法,因此每一个类都默认拥有它们。

       虽然所有的类都默认拥有这3个方法,但是只有在synchronized关键字作用的范围内,并且是同一个同步问题中搭配使用这3个方法时才有实际的意义。

这些方法在Object类中声明的语法格式如下所示:

final void wait() throws InterruptedExceptionfinal void notify()final void notifyAll()

      其中,调用wait()方法可以使调用该方法的线程释放共享资源的锁,然后从运行态退出,进入等待队列,直到被再次唤醒。而调用notify()方法可以唤醒等待队列中第一个等待同一共享资源的线程,并使该线程退出等待队列,进入可运行态。调用notifyAll()方法可以使所有正在等待队列中等待同一共享资源的线程从等待状态退出,进入可运行状态,此时,优先级最高的那个线程最先执行。显然,利用这些方法就不必再循环检测共享资源的状态,而是在需要的时候直接唤醒等待队列中的线程就可以了。这样不但节省了宝贵的CPU资源,也提高了程序的效率。

由于wait()方法在声明的时候被声明为抛出InterruptedException异常,因此,在调用wait()方法时,需要将它放入try…catch代码块中。此外,使用该方法时还需要把它放到一个同步代码段中,否则会出现如下异常:

"java.lang.IllegalMonitorStateException: current thread not owner"

这些方法是不是就可以实现线程间的通信了呢?下面将通过多线程同步的模型:生产者和消费者问题来说明怎样通过程序解决多线程间的通信问题。

案例:线程的通信

案例说明

下面这个程序演示了多个线程之间进行通信的具体实现过程。程序中用到了4个类,其中ShareData类用来定义共享数据和同步方法。在同步方法中调用了wait()方法和notify()方法,并通过一个信号量来实现线程间的消息传递。

实现过程

//CommunicationDemo.java 描述:生产者和消费者之间的消息传递过程

class ShareData{

private char c;

private boolean isProduced = false; // 信号量

public synchronized void putShareChar(char c) // 同步方法putShareChar()

{

if (isProduced){     // 如果产品还未消费,则生产者等待

try{

wait();        // 生产者等待

}catch(InterruptedException e){

e.printStackTrace();

}

}

this.c = c;

isProduced = true;   // 标记已经生产

notify();             // 通知消费者已经生产,可以消费

}


public synchronized char getShareChar() // 同步方法getShareChar()

{

if (!isProduced)    // 如果产品还未生产,则消费者等待

{

try{

wait();       // 消费者等待

}catch(InterruptedException e){

e.printStackTrace();

}

}

isProduced = false; // 标记已经消费

notify();            // 通知需要生产

return this.c;

}

}


class Producer extends Thread     // 生产者线程

{

private ShareData s;

Producer(ShareData s){

this.s = s;

}

public void run(){

for (char ch = ''A''; ch <= ''D''; ch++){

try{

Thread.sleep((int)(Math.random()*3000));

}catch(InterruptedException e){

e.printStackTrace();

}

s.putShareChar(ch); // 将产品放入仓库

System.out.println(ch + " is produced by Producer.");

}

}

}


class Consumer extends Thread    // 消费者线程

{

private ShareData s;

Consumer(ShareData s){

this.s = s;

}

public void run(){

char ch;

do{

try{

Thread.sleep((int)(Math.random()*3000));

}catch(InterruptedException e){

e.printStackTrace();

}

ch = s.getShareChar();    // 从仓库中取出产品

System.out.println(ch + " is consumed by Consumer. ");

}while (ch != ''D'');

}

}


class CommunicationDemo{

public static void main(String[] args){

ShareData s = new ShareData();

new Consumer(s).start();

new Producer(s).start();

}

}


转载于:https://my.oschina.net/u/1042978/blog/127183

相关文章:

  • nullnullHandling Features Not Supported on TV 在电视上处理不支持的功能
  • 我的vim高亮设置
  • 如何配置oracle数据库的连接
  • Java EE企业系统性能问题的原因和解决建议
  • 使用sqlplus创建表空间
  • 数据库并发操作
  • 列出目录下所有文件
  • Java 程序编译运行
  • Go语言并发之美
  • 我的PGA我作主----搞清楚什么是真正的PGA
  • PostgreSQL在何处处理 sql查询之十一
  • heartbeat 3.0集群(1)集群原理
  • 【乡巴佬】在Word中合理排列文本框与文本
  • c#类的初始化顺序
  • VIM使用系列:位置跳转和块模式
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • Apache Pulsar 2.1 重磅发布
  • chrome扩展demo1-小时钟
  • js正则,这点儿就够用了
  • laravel5.5 视图共享数据
  • Node + FFmpeg 实现Canvas动画导出视频
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • Phpstorm怎样批量删除空行?
  • php的插入排序,通过双层for循环
  • React-flux杂记
  • Redis在Web项目中的应用与实践
  • Selenium实战教程系列(二)---元素定位
  • yii2中session跨域名的问题
  • 让你的分享飞起来——极光推出社会化分享组件
  • 终端用户监控:真实用户监控还是模拟监控?
  • No resource identifier found for attribute,RxJava之zip操作符
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • $.ajax,axios,fetch三种ajax请求的区别
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (03)光刻——半导体电路的绘制
  • (办公)springboot配置aop处理请求.
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (六)Hibernate的二级缓存
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .net mvc 获取url中controller和action
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • @Transactional注解下,循环取序列的值,但得到的值都相同的问题
  • []C/C++读取串口接收到的数据程序
  • []使用 Tortoise SVN 创建 Externals 外部引用目录
  • [383] 赎金信 js
  • [Angular] 笔记 21:@ViewChild
  • [bzoj1038][ZJOI2008]瞭望塔
  • [C# 开发技巧]如何使不符合要求的元素等于离它最近的一个元素
  • [C#基础知识系列]专题十七:深入理解动态类型