[英]Java Multithreading program : Object sharing in multiple threads
我正在嘗試用 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();
}
}
這是多線程的一個很好的學習案例,我稍微更改了您的代碼。 請將 BankAccountManager 類與您的兩個類進行比較,我希望這會有所幫助。
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();
}
}
在DepositRunnable
和WithdrawalRunnable
,您從未初始化成員myAccount
,而是嘗試在它們各自的方法中使用它們。 在使用它們之前嘗試初始化這些成員。
BankAccount myAccount = new BankAccount();
可能還有更多的例子,但這些是我首先要看的。
存款和取款 Runnables 中的字段 MyAccount 未初始化
我看到的是屬性
BankAccount myAccount;
出現在類 DepositRunnable 和 WithdrawalRunnable 中的那個沒有被正確初始化,因此你會得到一個空指針異常,例如這里:
myAccount.withdraw(money_Withdrawn);
您的許多類成員變量都沒有被初始化。 您的具體問題是因為Wife.myDeposit
從未被初始化,但是一旦您通過了,就會有另一個 NPE 等着您。
是的,謝謝,所有這些類都需要初始化如下:
DepositRunnable myDeposit = new DepositRunnable();
WithdrawalRunnable myWithdrawal = new WithdrawalRunnable();
BankAccount myAccount = new BankAccount();
另一個沒人發現的錯誤是:“total”必須是靜態的。
謝謝大家。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.