简体   繁体   English

Java多线程程序:多线程对象共享

[英]Java Multithreading program : Object sharing in multiple threads

I am trying to make a program in Java that uses multithreading.我正在尝试用 Java 编写一个使用多线程的程序。 This program is about a bank account shared between husband and wife who use debit cards.该程序是关于使用借记卡的夫妻之间共享的银行帐户。

I wrote the Java program using 2 threads but i am getting java.lang.NullPointerException我使用 2 个线程编写了 Java 程序,但我收到了java.lang.NullPointerException

I am trying to buildup my knowledge in Java multithreading.我正在努力积累我在 Java 多线程方面的知识。 Help me in identifying the mistake in this code block.帮助我识别此代码块中的错误。

Here is the program :这是程序:

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

It is a good study case for multithread, I changed your code a little.这是多线程的一个很好的学习案例,我稍微更改了您的代码。 Please compare BankAccountManager class with your two classes, I hope this would help.请将 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();
    }
}

In both DepositRunnable and WithdrawalRunnable , you never initialize the member myAccount , but you attempt to use them in their respective methods.DepositRunnableWithdrawalRunnable ,您从未初始化成员myAccount ,而是尝试在它们各自的方法中使用它们。 Try initializing those members before you use them.在使用它们之前尝试初始化这些成员。

BankAccount myAccount = new BankAccount();

There may be more examples, but those are the first ones I would look at.可能还有更多的例子,但这些是我首先要看的。

存款和取款 Runnables 中的字段 MyAccount 未初始化

What I'm seeing is that the attribute我看到的是属性

BankAccount myAccount;

That appears in the classes DepositRunnable and WithdrawalRunnable is not being correctly initialized, hence you'll get a null pointer exception for example here:出现在类 DepositRunnable 和 WithdrawalRunnable 中的那个没有被正确初始化,因此你会得到一个空指针异常,例如这里:

myAccount.withdraw(money_Withdrawn);

Many of your class member variables are not being initialized.您的许多类成员变量都没有被初始化。 Your specific problem is because Wife.myDeposit has never been initialized, but once you get past that there will just be another NPE waiting for you.您的具体问题是因为Wife.myDeposit从未被初始化,但是一旦您通过了,就会有另一个 NPE 等着您。

Yes Thank you , all these classes need to be initialized as follows :是的,谢谢,所有这些类都需要初始化如下:

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

And the other mistake that nobody catch it is : "total" must be static .另一个没人发现的错误是:“total”必须是静态的。

Thank you everyone.谢谢大家。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM