• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > 详谈java线程与线程、进程与进程间通信

详谈java线程与线程、进程与进程间通信

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了进程间通信,linux进程间通信,android 进程间通信,c#进程间通信,java进程间通信等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

线程与线程间通信

一、基本概念以及线程与进程之间的区别联系:

关于进程和线程,首先从定义上理解就有所不同

1、进程是什么?

是具有一定独立功能的程序、它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说进程是可以独 立运行的一段程序。

2、线程又是什么?

线程进程的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源。

在运行时,只是暂用一些计数器、寄存器和栈 。

他们之间的关系

1、一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程(通常说的主线程)。

2、资源分配给进程,同一进程的所有线程共享该进程的所有资源。

3、线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。

4、处理机分给线程,即真正在处理机上运行的是线程。

5、线程是指进程内的一个执行单元,也是进程内的可调度实体。

从三个角度来剖析二者之间的区别

1、调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。

2、并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。

3、拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。.

二、多线程间通信方式:

1、共享变量

2、wait/notify机制

3、Lock/Condition机制

4、管道

三、共享变量

线程间发送信号的一个简单方式是在共享对象的变量里设置信号值。线程A在一个同步块里设置boolean型成员变量hasDataToProcess为true,线程B也在同步块里读取hasDataToProcess这个成员变量。这个简单的例子使用了一个持有信号的对象,并提供了set和check方法:


public class MySignal{

 protected boolean hasDataToProcess = false;

 public synchronized boolean hasDataToProcess(){
  return this.hasDataToProcess;
 }

 public synchronized void setHasDataToProcess(boolean hasData){
  this.hasDataToProcess = hasData;
 }

}

线程A和B必须获得指向一个MySignal共享实例的引用,以便进行通信。如果它们持有的引用指向不同的MySingal实例,那么彼此将不能检测到对方的信号。需要处理的数据可以存放在一个共享缓存区里,它和MySignal实例是分开存放的。

四、wait()/notify机制

为了实现线程通信,我们可以使用Object类提供的wait()、notify()、notifyAll()三个方法。调用wait()方法会释放对该同步监视器的锁定。这三个方法必须由同步监视器对象来调用,这可分成两种情况:

•对于使用synchronized修饰的同步方法,因为该类的默认实例是(this)就是同步监视器,所以可以直接调用这三使用个方法。

•对于synchronized修饰的同步代码块,同步监视器是synchronized括号里的对象,所以必须使用该对象调用这三个方法。

假设系统中有两条线程,这两条线程分别代表取钱者和存钱者。现在系统有一种特殊的要求,系统要求存款者和取钱者不断的实现存款和取钱动作,而且要求每当存款者将钱存入指定账户后,取钱者立即将钱取走.不允许存款者两次存钱,也不允许取钱者两次取钱。

我们通过设置一个旗标来标识账户中是否已有存款,有就为true,没有就标为false。具体代码如下:

首先我们定义一个Account类,这个类中有取钱和存钱的两个方法,由于这两个方法可能需要并发的执行取钱、存钱操作,所有将这两个方法都修改为同步方法.(使用synchronized关键字)。

public class Account { 
  private String accountNo; 
  private double balance; 
  //标识账户中是否有存款的旗标 
  private boolean flag=false; 
   
  public Account() { 
    super(); 
  } 
 
  public Account(String accountNo, double balance) { 
    super(); 
    this.accountNo = accountNo; 
    this.balance = balance; 
  }  
   
  public synchronized void draw (double drawAmount){ 
     
    try { 
       if(!flag){ 
       this.wait(); 
       }else { 
         //取钱 
         System.out.println(Thread.currentThread().getName()+" 取钱:"+drawAmount); 
         balance=balance-drawAmount; 
         System.out.println("余额 : "+balance); 
         //将标识账户是否已有存款的标志设为false 
         flag=false; 
         //唤醒其它线程 
         this.notifyAll();     
       } 
      } catch (Exception e) { 
        e.printStackTrace(); 
    } 
  } 
   
   
  public synchronized void deposit(double depositAmount){ 
   try { 
       if(flag){ 
        this.wait(); 
       } 
       else{ 
         System.out.println(Thread.currentThread().getName()+"存钱"+depositAmount); 
         balance=balance+depositAmount; 
         System.out.println("账户余额为:"+balance); 
         flag=true; 
         //唤醒其它线程 
         this.notifyAll(); 
       } 
    } catch (Exception e) { 
      // TODO: handle exception 
      e.printStackTrace(); 
    } 
  } 
 
} 
</div>

接下来创建两个线程类,分别为取钱和存钱线程!

取钱线程类:

public class DrawThread implements Runnable { 
 
  private Account account; 
  private double drawAmount; 
   
   
  public DrawThread(Account account, double drawAmount) { 
    super(); 
    this.account = account; 
    this.drawAmount = drawAmount; 
  } 
 
  public void run() { 
    for(int i=0;i<100;i++){ 
     account.draw(drawAmount);   
    } 
  } 
} 
</div>

存钱线程类:

public class depositThread implements Runnable{ 
  private Account account; 
  private double depositAmount; 
    
  public depositThread(Account account, double depositAmount) { 
    super(); 
    this.account = account; 
    this.depositAmount = depositAmount; 
  } 
 
 
  public void run() { 
  for(int i=0;i<100;i++){ 
     account.deposit(depositAmount); 
   } 
  } 
 
} 
</div>

最后我们测试一下这个取钱和存钱的操作

public class TestDraw { 
 
  public static void main(String[] args) { 
    //创建一个账户 
    Account account=new Account(); 
    new Thread(new DrawThread(account, 800),"取钱者").start(); 
    new Thread(new depositThread(account, 800),"存款者甲").start(); 
    new Thread(new depositThread(account, 800),"存款者乙").start(); 
    new Thread(new depositThread(account, 800),"存款者丙").start(); 
 
  } 
 
} 
</div>

大致的输出结果:

存款者甲存钱800.0 
账户余额为:800.0 
取钱者 取钱:800.0 
余额 : 0.0 
存款者丙存钱800.0 
账户余额为:800.0 
取钱者 取钱:800.0 
余额 : 0.0 
存款者甲存钱800.0 
账户余额为:800.0 
取钱者 取钱:800.0 
余额 : 0.0 
存款者丙存钱800.0 
账户余额为:800.0 
取钱者 取钱:800.0 
余额 : 0.0 
存款者甲存钱800.0 
账户余额为:800.0 
取钱者 取钱:800.0 
余额 : 0.0 
存款者丙存钱800.0 
账户余额为:800.0 
取钱者 取钱:800.0 
余额 : 0.0 
存款者甲存钱800.0 
账户余额为:800.0 
取钱者 取钱:800.0 
余额 : 0.0 
存款者丙存钱800.0 
账户余额为:800.0 
取钱者 取钱:800.0 
余额 : 0.0 
存款者甲存钱800.0 
账户余额为:800.0 
取钱者 取钱:800.0 
余额 : 0.0 
</div>

五、Lock/Condition机制

如何程序不使用synchronized关键字来保持同步,而是直接适用Lock对像来保持同步,则系统中不存在隐式的同步监视器对象,也就不能使用wait()、notify()、notifyAll()来协调线程的运行.

当使用LOCK对象保持同步时,JAVA为我们提供了Condition类来协调线程的运行。关于Condi

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 详谈java线程与线程、进程与进程间通信
  • 详谈java线程与线程、进程与进程间通信

相关文章

  • 2017-05-28Java 中的HashMap详解和使用示例_动力节点Java学院整理
  • 2017-05-28Java常用字符串工具类 字符串智能截取(3)
  • 2017-05-28Java递归算法详解(动力节点整理)
  • 2017-05-28Java微信公众平台开发(15) 微信JSSDK的使用
  • 2017-05-28TreeSet详解和使用示例_动力节点Java学院整理
  • 2017-05-28java方法重写和super关键字实例详解
  • 2017-05-28java 面试题闰年判断详解及实例
  • 2017-05-28Java 存储模型和共享对象详解
  • 2017-05-28Spring Boot启动过程(四)之Spring Boot内嵌Tomcat启动
  • 2017-05-28详解MyBatis批量插入数据Mapper配置文件的写法

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 详解Spring 基于 Aspect 注解的增强实现
    • Java中ArrayList的工作原理详解
    • spring boot 的常用注解使用小结
    • java实现合并单元格的同时并导出excel示例
    • 用java实现一个简易编译器1-词法解析入门
    • Java中的常用阻塞队列源码分析
    • Kotlin教程之函数和包的定义和流程控制
    • java对象拷贝详解及实例
    • Java中终止线程的方法详解
    • Spring Boot启动过程(五)之Springboot内嵌Tomcat对象的start教程详解

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有