• java中线程通信(传统的线程通信)


    假设现在系统有两个线程,这两个线程分别代表存款者和取钱者——现在假设系统有一种特殊的要求,系统要求存款者和取钱者不断地重复存款、取钱的动作。而且要求每当存款者将钱存入指定账户后,取钱者就立即取出该笔钱。不允许存款者连续两次存钱,也不允许取钱者连续两次取钱。

    为了实现这种功能,可以借助Object类提供的wait()、notify()、notifyAll() 3 个方法,这3个方法并不属于Thread类,而是属于Object类。但这3 个方法必须由同步监视器对象来调用,这可分以下两种情况:

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

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

    关于这3个方法的解释如下:

    wait():导致当前线程等待,直到其他线程调用该同步监视器的notify()方法或notifyAll()方法来唤醒该线程。该wait()方法有三种形式——无时间参数的wait(一直等待,知道其他线程通知),带毫秒参数的wait和带毫秒、毫微妙参数的wait(这两种方法都是等待指定时间后自动苏醒) 调用wait方法的当前线程会释放对该同步监视器的锁定。

    notify():唤醒在次同步监视器上等待的单个线程。如果所有的线程都在此同步监视器上等待,则会选择唤醒其中一个线程。选择是任意的。只有当前线程放弃对该同步监视器的锁定后(使用wait方法),才可以执行被唤醒的线程。

    notifyAll():唤醒在此同步监视器上等待的所有线程。只有当前线程放弃对同步监视器的锁定后,才可以执行被唤醒的线程。

     1 public class DrawTest{
     2     public static void main(String[] args){
     3         Account a=new Account("刘腾",10000);
     4         new DrawThread(a,100).start();
     5         new InThread(a,50).start();
     6         new InThread(a,60).start();
     7         new InThread(a,70).start();
     8     }
     9 }
    10 //账户类
    11 class Account{
    12     private String name;
    13     private double money;
    14     private boolean flag=false;
    15     
    16     public Account(){}
    17     public Account(String name,double money){
    18         this.name=name;
    19         this.money=money;
    20     }
    21     public double getMoney(){
    22         return money;
    23     }
    24     public synchronized void draw(double drawmoney){
    25             try{
    26             //如果flag为假,说明还没有人往里面存钱,所以让该线程等待。
    27                 if(!flag){
    28                     wait();
    29                 }else{
    30                     System.out.println("取出钱数为:"+drawmoney+" 剩余钱数:"+(getMoney()-drawmoney));
    31                     flag=false;
    32                     notifyAll();
    33                 }
    34             }catch(Exception e){System.out.println(e);}
    35         }
    36     public synchronized void deposit(double inmoney){
    37         try{
    38             if(!flag){
    39                 System.out.println("存入钱数为:"+inmoney+" 目前的钱数为:"+(getMoney()+inmoney));
    40                 flag=true;
    41                 notifyAll();
    42             }else{
    43                 wait();
    44             }
    45         }catch(Exception e){}
    46     } 
    47 }
    48 //取钱线程
    49 class DrawThread extends Thread{
    50     private Account account;
    51     private double drawmoney;
    52     
    53     public DrawThread (Account account,double drawmoney){
    54         this.account=account;
    55         this.drawmoney=drawmoney;
    56     }
    57     public void run(){
    58         for(int i=0;i<100;i++){
    59             account.draw(drawmoney);
    60         }
    61     }
    62 }
    63 class InThread extends Thread{
    64     private Account account;
    65     private double inmoney;
    66     
    67     public InThread(Account account,double inmoney){
    68         this.account=account;
    69         this.inmoney=inmoney;
    70     }
    71     public void run(){
    72         for(int k=0;k<100;k++){
    73             account.deposit(inmoney);
    74         }
    75     }
    76 }
  • 相关阅读:
    django 开发Broken pipe from ('127.0.0.1', 58078)问题解决
    cocos2d-js中jsc逆向为js攻略
    ECshop 怎样修改商品详细页的“浏览次数”
    ecshop 加广告出现广告位的宽度值必须在1到1024之间
    Nginx 301重定向的配置
    ECSHOP安装百度编辑UEditor教程
    Ecshop商品详情页显示当前会员等级价格
    ECSHOP始终显示全部分类方法
    vps主机修改系统远程端口号/添加防火墙
    ecshop利用.htaccess实现301重定向的方法
  • 原文地址:https://www.cnblogs.com/teng-IT/p/4451670.html
Copyright © 2020-2023  润新知