• 线程通讯-传统方式


    1.传统方式1

    一个NumberHolder2类

    package com.thread.comm;
    
    public class NumberHolder2 {
        private int number;
    
        public synchronized void increase()
        {
            
                try
                {
                    for(int i=0;i<1000;i++){
                        if (0 != number){
                            System.out.println(Thread.currentThread().getName()+"----"+ i +"被阻塞"+ number);
                            wait();    
                        }else{
                             // 能执行到这里说明已经被唤醒
                            // 并且number为0
                            number++;
                            System.out.println(Thread.currentThread().getName()+"----"+ i +"----"+ number);
    
                            // 通知在等待的线程
                            notifyAll();                  
                        }
                        
                    }
                                  
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            
    
           
        }
    
        public synchronized void decrease()
        {
            
            
                try
                {
                    for(int i =0 ;i<100;i++){
                        if (0 == number){
                            System.out.println(Thread.currentThread().getName()+"----"+ i +"被阻塞"+ number);
                            wait();
                        }else{
                            // 能执行到这里说明已经被唤醒
                            // 并且number不为0
                            number--;
                            System.out.println(Thread.currentThread().getName()+"----"+ i +"----"+ number);
                            notifyAll();                   
                        }
                        
                    }
                                   
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            
        }
    
    }

    两个操作线程

    package com.thread.comm;
    
    public class IncreaseThread extends Thread{
        private NumberHolder2 numberHolder;
    
        public IncreaseThread(String name,NumberHolder2 numberHolder)
        {
            super(name);
            this.numberHolder = numberHolder;
        }
    
        @Override
        public void run()
        {
            for (int i = 0; i < 20; ++i)
            {
                // 进行一定的延时
                try
                {
                    Thread.sleep((long) Math.random() * 1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
    
                // 进行增加操作
                numberHolder.increase();
            }
        }
    
    }
    package com.thread.comm;
    
    public class DecreaseThread extends Thread
    {
        private NumberHolder2 numberHolder;
    
        public DecreaseThread(String name,NumberHolder2 numberHolder)
        {
            super(name);
            this.numberHolder = numberHolder;
        }
    
        @Override
        public void run()
        {
            for (int i = 0; i < 20; ++i)
            {
                // 进行一定的延时
                try
                {
                    Thread.sleep((long) Math.random() * 1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
    
                // 进行减少操作
                numberHolder.decrease();
            }
        }
    
    }

    执行

    package com.thread.comm;
    
    public class NumberTest {
        public static void main(String[] args)
        {
            NumberHolder2 numberHolder = new NumberHolder2();
               
            new IncreaseThread("加1-1",numberHolder).start();
            new DecreaseThread("减2-1",numberHolder).start();
            new DecreaseThread("减2-2",numberHolder).start();
        }
    
    }

    运行结果

    。。。
    减2-2----98被阻塞0
    加1-1----192----1
    加1-1----193被阻塞1
    减2-2----99----0
    减2-1----92被阻塞0
    加1-1----194----1
    加1-1----195被阻塞1
    减2-1----93----0
    减2-1----94被阻塞0
    加1-1----196----1
    加1-1----197被阻塞1
    减2-1----95----0
    减2-1----96被阻塞0
    加1-1----198----1
    加1-1----199被阻塞1
    减2-1----97----0
    减2-1----98被阻塞0
    加1-1----200----1
    加1-1----201被阻塞1
    减2-1----99----0
    加1-1----202----1
    加1-1----203被阻塞1

    从结果上可以验证出 线程执行存在随机性。

    1.如果是一增加一减少两条线程,也可能出现一个线程进程先死亡,导致另外一个线程没有被唤醒,导致整个进程一致处于阻塞状态。

    2.一定情况下可以使用wait(1000),通过时间设定,使得处于阻塞状态的线程进入就绪状态,从而保证整个进程执行完成。例如可以将NumberHolder2中的wait()改成wait(1000).

     2.传统通讯2---在同一个账户中有多个线程进行存钱和取钱

    account类

    package com.thread.communication.tradition;
    
    public class Account {
        private String accountNo;
        private double balance;
        
        private boolean flag =false;
        
        public Account(){}
        
        public Account(String accountNo , double balance){
            this.accountNo=accountNo;
            this.balance=balance;
        }
        
        public void setAccountNo(String num){
            this.accountNo=num;
        }
    
        public String getAccountNo(){
            return this.accountNo;        
        }
        
        public double getBalance(){
            return this.balance;
            
        }
        
        public synchronized void draw(double drawAmount){
            try{
                if(!flag){
                    wait();
                }else{
                    System.out.println(Thread.currentThread().getName() + "取钱: " + drawAmount);
                    this.balance-=drawAmount;
                    System.out.println("当前余额是: "+ balance);
                    flag = false;
                    notifyAll();
                }
            }catch(InterruptedException ex){
                ex.printStackTrace();            
            }
            
        }
        
        public synchronized void deposit(double depositAmount){
            try{
                System.out.println("开始存钱");
                if(flag){
                    wait();
                }else{
                    System.out.println(Thread.currentThread().getName() + "存钱: " + depositAmount);
                    this.balance+=depositAmount;
                    System.out.println("当前余额是: "+ balance);
                    flag = true;
                    notifyAll();
                }
            }catch(InterruptedException ex){
                ex.printStackTrace();            
            }
        }
        
        public int hashCode(){
            return accountNo.hashCode();        
        }
        
        public boolean equals(Object obj){
            if(this == obj)
                return true;
            if(obj !=null 
                    && obj.getClass()==Account.class){
                Account target =(Account)obj;
                return target.getAccountNo().equals(accountNo);
            }
            return false;        
        }
        
    }

    两个线程类

    package com.thread.communication.tradition;
    
    public class DepositThread extends Thread{
    
        private Account account;
        private double depositAmount;
        
        public DepositThread(String name,Account account,double depositAmount){
            super(name);
            this.account=account;
            this.depositAmount=depositAmount;
        }
        
    
        public void run(){
            for (int i=0;i<100;i++){
                account.deposit(depositAmount);
            }
        }
    }
    package com.thread.communication.tradition;
    
    public class DrawThread extends Thread{
        private Account account;
        private double drawAmount;
        
        public DrawThread(String name,Account account,double drawAmount){
            super(name);
            this.account=account;
            this.drawAmount=drawAmount;
        }
        
        public void run(){
            for (int i=0;i<100;i++){
                account.draw(drawAmount);
            }
        }
    }

    测试类

    package com.thread.communication.tradition;
    
    public class DrawTest {
    
        public static void main(String[] args) {
            Account acct = new Account("account1",0.0);
            System.out.println(acct.getAccountNo() + " " + acct.getBalance());
            new DepositThread("存钱者甲",acct,800.0).start();
            new DepositThread("存钱者已",acct,800.0).start();
            new DepositThread("存钱者丙",acct,800.0).start();
            new DrawThread("取钱者",acct,800.0).start();        
        }
    
    }

     

  • 相关阅读:
    读书笔记之:数据结构,算法与应用(3)
    C++中的虚函数继承与虚继承
    读书笔记之:Effective STL
    C++虚函数及虚函数表解析
    类中的常量, const对象和成员函数
    读书笔记之:Boost程序库完全开发指南(Ch14)
    读书笔记之:C++探秘——68讲贯通C++
    读书笔记之:Boost程序库完全开发指南(ch516)
    配置java的环境变量
    查询并杀死死锁
  • 原文地址:https://www.cnblogs.com/moonpool/p/5496887.html
Copyright © 2020-2023  润新知