2

マルチスレッドを使用する Java でプログラムを作成しようとしています。このプログラムは、デビットカードを使用する夫と妻の間で共有される銀行口座に関するものです。

2 つのスレッドを使用して Java プログラムを作成しましたが、java.lang.NullPointerException

Java マルチスレッドに関する知識を蓄積しようとしています。このコード ブロックの間違いを特定するのを手伝ってください。

プログラムは次のとおりです。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;


// A bank account has a balance that can be changed by deposits and withdrawals.

public class BankAccount {

    public double total = 0, amount = 0;

    public void withdraw(double amount) {
        total -= amount;
        System.out.println("Amount Withdrawn is " + amount);
    }

    public void deposit(double amount) {
        total += amount;
        System.out.println("Amount Deposited is " + amount);
    }

    public double getAccount() {
        System.out.println("Total Amount is " + total);
        return total;

    }
}

class WithdrawalRunnable {

    private static final Lock lock = new ReentrantLock();
    final Condition myCond = lock.newCondition();
    BankAccount myAccount;

    public void amountWithdrawn(double money_Withdrawn) throws InterruptedException {
        lock.lock();
        try {
            while (money_Withdrawn > myAccount.total) {
                myCond.await();  
                //when the condition is satisfied then :
                myAccount.withdraw(money_Withdrawn);
                myAccount.getAccount();
            }
        } finally {
            lock.unlock();
        }
    }
}

class DepositRunnable {

    private static final Lock lock = new ReentrantLock();
    final Condition myCond = lock.newCondition();
    BankAccount myAccount;

    public void amountDeposited(double money_deposited) throws InterruptedException {
        lock.lock();
        try {
            myAccount.deposit(money_deposited);
            myAccount.getAccount();
            myCond.signalAll(); 
        } finally {
            lock.unlock();
        }
    }
}

class Husband implements Runnable {

    DepositRunnable myDeposit;
    WithdrawalRunnable myWithdrawal;
    double amount_deposit;
    double amount_withdraw;

    public Husband(double amount_deposit, double amount_withdraw) {
        this.amount_deposit = amount_deposit;
        this.amount_withdraw = amount_withdraw;
    }

    public void run() {
        try {
            myDeposit.amountDeposited(amount_deposit);
            myWithdrawal.amountWithdrawn(amount_withdraw);
        } catch (InterruptedException ex) {
            Logger.getLogger(Wife.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

class Wife implements Runnable {

    DepositRunnable myDeposit;
    WithdrawalRunnable myWithdrawal;
    double amount_deposit;
    double amount_withdraw;

    public Wife(double amount_deposit, double amount_withdraw) {
        this.amount_deposit = amount_deposit;
        this.amount_withdraw = amount_withdraw;
    }

    public void run() {
        try {
            myDeposit.amountDeposited(amount_deposit);
            myWithdrawal.amountWithdrawn(amount_withdraw);
        } catch (InterruptedException ex) {
            Logger.getLogger(Wife.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}

class RunningThreadTest {

    public static void main(String[] args) throws InterruptedException {

        Husband husb = new Husband(100.0, 0.0);
        Wife wif = new Wife(400.0, 0.0);
        Thread thread1 = new Thread(husb);
        Thread thread2 = new Thread(wif);
        thread1.start();
        thread2.start();
    }
}
4

6 に答える 6

2

マルチスレッドの良い研究例です。コードを少し変更しました。BankAccountManager クラスとあなたの 2 つのクラスを比較してください。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;

// A bank account has a balance that can be changed by deposits and withdrawals.

class BankAccount {

    private double total = 0;

    public void withdraw(double amount) {
        total -= amount;
    }

    public void deposit(double amount) {
        total += amount;
    }

    public double getAccount() {
        return total;

    }
}

class BankAccountManager {

    private static final Lock lock = new ReentrantLock();
    private Condition myCond = lock.newCondition();
    BankAccount myAccount;

    public BankAccountManager(BankAccount myAccount) {
        this.myAccount = myAccount;
    }

    public void amountWithdrawn(double money_Withdrawn)
            throws InterruptedException {
        lock.lock();
        try {
            if (money_Withdrawn > myAccount.getAccount()) {
                myCond.await();
            }
            // when the condition is satisfied then :
            System.out.println("Amount Withdrawn is " + money_Withdrawn);
            myAccount.withdraw(money_Withdrawn);
            System.out.println("Total Amount is " + myAccount.getAccount());
        } finally {
            lock.unlock();
        }
    }

    public void amountDeposited(double money_deposited)
            throws InterruptedException {
        lock.lock();
        try {
            System.out.println("Amount Deposited is " + money_deposited);
            myAccount.deposit(money_deposited);
            System.out.println("Total Amount is " + myAccount.getAccount());
            myCond.signalAll();
        } finally {
            lock.unlock();
        }
    }
}

class Husband implements Runnable {

    private BankAccountManager manager;
    private double amount_deposit;
    private double amount_withdraw;

    public Husband(BankAccountManager manager, double amount_deposit,
            double amount_withdraw) {
        this.manager = manager;
        this.amount_deposit = amount_deposit;
        this.amount_withdraw = amount_withdraw;
    }

    public void run() {
        try {
            manager.amountDeposited(amount_deposit);
            manager.amountWithdrawn(amount_withdraw);
        } catch (InterruptedException ex) {
            Logger.getLogger(Wife.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

class Wife implements Runnable {

    private BankAccountManager manager;
    private double amount_deposit;
    private double amount_withdraw;

    public Wife(BankAccountManager manager, double amount_deposit,
            double amount_withdraw) {
        this.manager = manager;
        this.amount_deposit = amount_deposit;
        this.amount_withdraw = amount_withdraw;
    }

    public void run() {
        try {
            manager.amountDeposited(amount_deposit);
            manager.amountWithdrawn(amount_withdraw);
        } catch (InterruptedException ex) {
            Logger.getLogger(Wife.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}

public class RunningThreadTest {

    public static void main(String[] args) throws InterruptedException {

        BankAccountManager manager = new BankAccountManager(new BankAccount());

        Husband husb = new Husband(manager, 100.0, 0.0);
        Wife wif = new Wife(manager, 400.0, 1.0);
        Thread thread1 = new Thread(husb);
        Thread thread2 = new Thread(wif);
        thread1.start();
        thread2.start();
    }
}
于 2012-09-19T02:44:56.897 に答える
1

との両方DepositRunnableWithdrawalRunnable、メンバーmyAccountを初期化することはありませんが、それぞれのメソッドでそれらを使用しようとします。それらを使用する前に、それらのメンバーを初期化してみてください。

BankAccount myAccount = new BankAccount();

もっと例があるかもしれませんが、それらは私が最初に見るものです。

于 2012-09-19T00:57:37.793 に答える
1

DepositRunnablesとWithdrawalRunnablesの両方のフィールドMyAccountが初期化されていません

于 2012-09-19T00:57:44.363 に答える
1

クラスメンバー変数の多くは初期化されていません。あなたの特定の問題は、Wife.myDeposit初期化されていないためですが、それを過ぎると、別のNPEがあなたを待っているだけです。

于 2012-09-19T01:16:54.123 に答える
1

私が見ているのは、属性が

BankAccount myAccount;

これはクラス DepositRunnable および WithdrawalRunnable に表示され、正しく初期化されていないため、たとえば次のように null ポインター例外が発生します。

myAccount.withdraw(money_Withdrawn);
于 2012-09-19T00:58:12.637 に答える
0

はい、ありがとうございます。これらのクラスはすべて、次のように初期化する必要があります。

DepositRunnable myDeposit = new DepositRunnable();
WithdrawalRunnable myWithdrawal = new WithdrawalRunnable();
BankAccount myAccount = new BankAccount();

そして、誰も気付かないもう 1 つの間違いは、"total" は static でなければならないということです。

みんなありがとう。

于 2012-09-19T01:28:26.720 に答える