线程通讯-传统方式

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();        
    }

}

 

 

 

 

posted @ 2016-05-16 10:55  月色深潭  阅读(196)  评论(0编辑  收藏  举报