在这个多线程java应用程序中,只有一个线程像顺序程序一样运行?

在这个多线程java应用程序中,只有一个线程像顺序程序一样运行?,java,multithreading,concurrency,Java,Multithreading,Concurrency,抱歉,描述太长了。如果时间太长,请告诉我如何改进 我正在学习Java并发性。这是我试图编写的一个场景 母亲和孩子共用一个银行账户。母子线程是两个独立的线程,从程序的主线程开始 在两者的run()中,它们执行多个银行交易。为简单起见,孩子只做取款交易,母亲只做存款交易。每个事务也是一个单独的线程。孩子/母亲必须等到一个事务完成后才能开始下一个事务。(等待/notifyAll用于此操作) 如果取款任务尝试取款,但余额不足(余额最初为0),则线程将进入while循环,等待余额大于取款金额 母亲在每次存

抱歉,描述太长了。如果时间太长,请告诉我如何改进

我正在学习Java并发性。这是我试图编写的一个场景

母亲和孩子共用一个银行账户。母子线程是两个独立的线程,从程序的主线程开始

在两者的run()中,它们执行多个银行交易。为简单起见,孩子只做取款交易,母亲只做存款交易。每个事务也是一个单独的线程。孩子/母亲必须等到一个事务完成后才能开始下一个事务。(等待/notifyAll用于此操作)

如果取款任务尝试取款,但余额不足(余额最初为0),则线程将进入while循环,等待余额大于取款金额

母亲在每次存款任务之间睡眠500毫秒

我所期望的

由于母亲在每次存款之间睡觉,而孩子在取款期间不睡觉,因此可以保证孩子的任务在循环时输入
资金不足。然而,由于母亲是一个单独的线程,等待500毫秒后,它将存款一些钱。然后孩子的取款任务线程会注意到这一点,退出while循环并完成事务

发生了什么

孩子进入一个无限循环,试图退出。母亲的线不会沉积

我有一种预感,这与wait()有关。当我从child调用task.wait()时,它正在等待task类的这个特定实例调用notify()对吗?不是任务类的所有实例


对母亲和孩子都是如此。我得到了相同的输出。

母线程和子线程正在等待相同的
任务
对象,因此如果调用
任务。notifyAll()
,它们将被唤醒。然而,事实并非如此。当存款更多时,
账户
会调用
notifyAll

这个实现的主要问题是任务是一个单独的线程。如果您仍然希望保持这种状态,那么您可以这样做:

首先:Account.draw使用
睡眠等待。相反,它应该使用
wait()
,这样当
Account.deposit
调用
notifyAll
时,它就可以醒来了

您的
母亲
孩子
线程可以等待
任务
,但是
任务
必须通知他们。因此,在
任务结束时,运行
您应该调用
notifyAll
来唤醒等待任务的所有线程


实际上,您正在使用三个线程来运行一个顺序任务。

除了其他问题外,
System.out.println
在内部是同步的。您好,按照您的建议执行了。仍然得到同样的回应。更新了有问题的代码。我想我知道出了什么问题。我改变了答案。母亲和孩子仍然应该等待任务,但任务必须等待。我现在明白了。谢谢:)
public class Test {
    public static void main(String[] args) {
        Account account = new Account();
        new Child("Bob", account).start();
        new Mother("mary", account).start();

    }
}

class Child extends Thread {
    String name;
    Account account;

    public Child(String name, Account account) {
        super("Child");
        this.name = name;
        this.account = account;
    }

    private void transaction(int val, TaskType taskType) {
        Task task = new Task(account, taskType, val);
        task.start();
        synchronized (task) {
            try {
                task.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public void run() {
        this.transaction(100, TaskType.WITHDRAW);
        System.out.println("100 WITHDRAW");
        this.transaction(150, TaskType.WITHDRAW);
        System.out.println("150 WITHDRAW");
        this.transaction(200, TaskType.WITHDRAW);
        System.out.println("200 WITHDRAW");
        this.transaction(500, TaskType.WITHDRAW);
        System.out.println("500 WITHDRAW");
    }
}

class Mother extends Thread {
    String name;
    Account account;

    public Mother(String name, Account account) {
        super("Mother");
        this.name = name;
        this.account = account;
    }

    private void transaction(int val, TaskType taskType) {
        Task task = new Task(account, taskType, val);
        task.start();
        synchronized (task) {
            try {
                task.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public void run() {
        this.transaction(100, TaskType.DEPOSIT);
        System.out.println("100 DEPOSIT");
        try {
            Thread.sleep(600);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.transaction(150, TaskType.DEPOSIT);
        try {
            Thread.sleep(600);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("150 DEPOSIT");
        this.transaction(200, TaskType.DEPOSIT);
        try {
            Thread.sleep(600);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("200 DEPOSIT");
        this.transaction(500, TaskType.DEPOSIT);
        try {
            Thread.sleep(600);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("500 DEPOSIT");
    }
}

class Task extends Thread {
    private static int id = 0;
    Account account;
    TaskType taskType;
    int val;

    public Task(Account account, TaskType taskType, int val) {
        super("Task");
        this.account = account;
        this.taskType = taskType;
        this.val = val;
    }

    @Override
    public void run() {
        switch (taskType) {
            case WITHDRAW:
                account.withdraw(val, id);
                break;
            case DEPOSIT:
                account.deposit(val, id);
                break;
        }
        id += 1;
    }
}

class Account {
    int balance = 0;

    public synchronized void deposit(int val, int id) {
        this.balance += val;
        this.notifyAll();

    }

    public synchronized void withdraw(int val, int id) {
        while (this.balance < val) {
            System.out.println("Funds insufficient waiting..." + id);

            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.balance -= val;
        System.out.println("Withdrawal successful " + id);
        this.notifyAll();
    }
}

enum TaskType {
    DEPOSIT,
    WITHDRAW
}
private void transaction(int val, TaskType taskType) {
    Task task = new Task(account, taskType, val);
    task.start();
    synchronized (account) {
        try {
            account.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}