日期:2014-05-20  浏览次数:20755 次

java 线程同步题目,有点儿小问题。
蓝色字体是考试题目:
预备知识:.生产者-消费者模式。在通信软件开发中,经常涉及到消息的处理,实现时会采用生产者-消费者模式:在同一个进程地址空间内执行的两个线程。
生产者线程产生消息,然后将消息放置在一个缓冲区内中供消费者线程处理。
消费者线程从缓冲区中读取消息进行处理。
当生产者线程产生消息时,如果缓冲区满,那么生产者线程必须等待消费者线程处理完消息以释放缓冲区,当消费者线程在读取消息进行处理时,如果缓冲区中没有消息,那么消费者线程将被阻塞,直到有消息被生产出来。
题目:
以银行存款和取款为背景,存款(生产)清单为add.txt,取款(消费)清单为take.txt。

add.txt格式如下:
Max:1000
List:100,300,800,500,400,200,600,700

take.txt格式如下:
Min:100
List:300,800,500,400,100,700,600,300

说明:
Max表示帐户的最大余额;Min表示帐户的最小余额;List表示存、取款的顺序清单。

要求:
命令行使用接口:
java BankOperation文件名 “BankOperation”参数是你将要实现的主程序类名,
该类有main方法public static void main(String [] args),是程序的入口。
控制台输出:
输出存取款的过程清单(List)和余额(Balance,不足时为负数),格式如下:
List:add100,add300,take300,add800。。。。。。。。。。。。
Balance:-200

提示:
余额说明:
当存款操作已经全部结束,取款出现不足时,余额为负数(所缺金额的总和,不要漏算帐户的最小余额)。



我对题目的要求的理解为:存钱时有上限,若超过上限,让给取钱线程运行。
取钱时有下限,如果超过下限让存钱线程运行。
但若存钱线程全部运行结束了,那么取钱线程就没有下限了,可以取到负数。
最后的正确答案应该是-100。

下面是我写的代码,但有点bug,有时运行程序会停住,导致最后一次的扣钱没有成功。不知道错在哪里?请各位帮忙看看吧,我的脑容量着实不够用了。

Java code

package com.soko.quiz;

public class BankOperation
{
    public static void main(String[] args) throws Exception
    {
        int[] addList = new int[]{100, 300, 800, 500, 400, 200, 600, 700};
        int[] takeList = new int[]{300, 800, 500, 400, 100, 700, 600, 300};
        
        Balance balance = new Balance();
        Thread adder = new Adder(balance, addList);
        Thread taker = new Taker(balance, takeList);
        
        System.out.print("List:");
        adder.start();
        taker.start();
        
        Thread.sleep(500);
        System.out.println("\nBalance:" + balance.getMoney()); //正确答案是 -100
    }
}

class Balance {
    
    private int money = 0;
    boolean isAddOver = false;
    
    public synchronized int getMoney()
    {
        return this.money;
    }
    
    public synchronized void add(int num) throws Exception
    {
        this.notifyAll();
        while((money + num) > 1000)
        {
            this.wait();
        } 
        
        money += num;
        
        System.out.print("add" + num + ", ");
System.out.println("balance:" + money);
    }
    
    public synchronized void take(int num) throws Exception
    {
        this.notifyAll();
        while((money - num) < 100 && !isAddOver)
        {        
            this.wait();
System.out.println("陷入循环无法跳出。 此时的money=" + money + "此时isAddOver=" + isAddOver);        
            
        }
        money -= num;
        
        System.out.print("take" + num + ", ");
System.out.println("balance:" + money);
    }
    
}

class Adder extends Thread {
    
    private Balance balance;
    private int[] addList;
    public Adder(Balance balance, int[] addList)
    {
        this.balance = balance;
        this.addList = addList;
    }
    
    public void run()
    {
        for(int i=0; i<addList.length; i++)
        {
            try
            {
                balance.add(addList[i]);
            }
            catch (Exception e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    }
    
}

class Taker extends Thread {
    
    private Balance balance;
    private int[] takeList;
    public Taker(Balance balance, int[] takeList)
    {
        this.balance = balance;
        this.takeList = takeList;
    }
    
    public void run()
    {
        for(int i=0; i<takeList.length; i++)
        {
            try
            {
                balance.take(takeList[i]);
            }
            catch (Exception e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
}