gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 09:10:45 25 4
gpt4 key购买 nike

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

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

一位母亲和一个 child 共用一个银行账户。 mother和child是两个独立的线程,从程序的主线程启动。

在两者的 run() 中,它们执行多项银行交易。为简单起见, child 只进行提取交易,母亲只进行存款交易。每个事务也是一个单独的线程。 child /母亲必须等到一笔交易完成才能开始下一笔交易。 (为此使用 wait/notifyAll)。

如果提现任务尝试提现,但余额不足(初始余额为0),则线程进入while循环,等待余额大于提现金额。

母亲在每次存款任务之间 hibernate 500 毫秒。

我的预期

由于母亲在每次存款期间 sleep ,而 child 在取款期间不 sleep ,因此可以保证 child 的任务将进入资金不足的 while 循环。但是,由于 mother 是一个单独的线程,因此等待 500ms 后它会存入一些钱。那么子进程的提现任务线程就会注意到这一点,跳出 while 循环并完成交易。

发生了什么

child 进入无限循环并试图退出。母线不存。

我有预感这与 wait() 有关。当我从子进程调用task.wait()时,它正在等待Task类的这个特定实例调用notify(),对吧?并非 Task 类的所有实例。

enter image description here

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

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

最佳答案

MotherChild线程正在等待相同的 task对象,所以如果你调用task.notifyAll(),他们就会醒来。 。然而,事实并非如此。这是account调用 notifyAll当存入更多的钱时。

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

首先:Account.withdraw 等待 Sleep 。相反,它应该使用 wait() ,所以当 Account.deposit来电 notifyAll ,它可以醒来。

您的MotherChild线程可以等待 task ,但随后 task必须通知他们。所以在 Task.run 的末尾你应该打电话notifyAll唤醒等待该任务的所有线程。

您实际上是使用三个线程来运行顺序任务。

关于java - 在这个多线程java应用程序中,只有一个线程似乎像顺序程序一样运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59442398/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com