英文:
Why is the code just after wait method not invoked
问题
我有一个客户账户类,其中有以下2个方法,addBalance和deductBalance。
class CustomerAccount
{
private int balance;
int getBalance() { return balance; }
CustomerAccount() { balance = 0; }
boolean deductBalance(final int amount)
{
System.out.println("> invoked to deduct :" + amount);
synchronized (this)
{
while (balance <= amount)
{
try { wait(); } catch (InterruptedException e) { TestWaitNotifyBasic.logException(e); }
System.out.println("> hey I was notified for cutting amount:" + amount);
}
balance -= amount;
}
System.out.println("> deducted:" + amount);
return true;
}
boolean addBalance(final int amount)
{
synchronized (this)
{
balance += amount;
notifyAll();
}
System.out.println("> balance added: " + amount);
return true;
}
}
下面是带有主方法的消费类。其思想是让线程在同步块中等待,直到调用notifyAll。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.IntFunction;
public class TestWaitNotifyBasic
{
public static void main(String[] args)
{
final CustomerAccount chuck = new CustomerAccount();
IntFunction<Runnable> addBalance = (amount) -> { return () -> chuck.addBalance(amount); };
IntFunction<Runnable> deductBalance = (amount) -> { return () -> chuck.deductBalance(amount); };
ExecutorService threadPool = Executors.newFixedThreadPool(100);
//balance deduction
threadPool.execute(deductBalance.apply(1000));
threadPool.execute(deductBalance.apply(50));
threadPool.execute(deductBalance.apply(5000));
//balance addition
threadPool.execute(addBalance.apply(900));
threadPool.execute(addBalance.apply(40));
threadPool.execute(addBalance.apply(80));
threadPool.execute(addBalance.apply(8000));
threadPool.shutdown();
while (!threadPool.isTerminated())
{
try { Thread.sleep(300); } catch (InterruptedException e) { logException(e); }
}
System.out.println("----------------------");
System.out.println("thread operations finished, final balance : " + chuck.getBalance());
int actualBalance = (900 + 40 + 80 + 8000) - (1000 + 50 + 5000);
System.out.println("Validity check " + actualBalance);
}
static void logException(InterruptedException e)
{
System.out.println("###########interruptedexception#########" + e);
}
}
以下是我的控制台输出
balance added: 80
invoked to deduct :1000
balance added: 8000
invoked to deduct :5000
invoked to deduct :50
balance added: 900
balance added: 40
deducted:5000
deducted:50
deducted:1000
thread operations finished, final balance : 2970
Validity check 2970
我要问的问题是,为什么下面这部分没有在控制台输出中打印出来:
> System.out.println("> hey I was notified for cutting amount:" + amount);
这个方法紧跟在CustomerAccount类中deductBalance方法的wait()方法旁边。
英文:
I have a customer account class with below 2 methods, addBalance and deductBalance.
class CustomerAccount
{
private int balance;
int getBalance() { return balance;}
CustomerAccount() {balance=0;}
boolean deductBalance(final int amount)
{
System.out.println("> invoked to deduct :" + amount);
synchronized (this)
{
while (balance <= amount)
{
try {wait(); } catch (InterruptedException e) {TestWaitNotifyBasic.logException(e);}
System.out.println("> hey I was notified for cutting amount:" + amount);
}
balance-= amount;
}
System.out.println("> deducted:" + amount);
return true;
}
boolean addBalance(final int amount)
{
synchronized (this)
{
balance += amount;
notifyAll();
}
System.out.println("> balance added: " + amount);
return true;
}
}
Below is the consuming class with main method. The idea is to have threads wait for synchronized block until notifyAll is called.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.IntFunction;
public class TestWaitNotifyBasic
{
public static void main(String[] args)
{
final CustomerAccount chuck = new CustomerAccount();
IntFunction<Runnable> addBalance = (amount) -> { return () -> chuck.addBalance(amount);};
IntFunction<Runnable> deductBalance = (amount) -> { return () -> chuck.deductBalance(amount);};
ExecutorService threadPool = Executors.newFixedThreadPool(100);
//balance deduction
threadPool.execute(deductBalance.apply(1000) );
threadPool.execute(deductBalance.apply(50) );
threadPool.execute(deductBalance.apply(5000));
//balance addition
threadPool.execute(addBalance.apply(900));
threadPool.execute(addBalance.apply(40));
threadPool.execute(addBalance.apply(80));
threadPool.execute(addBalance.apply(8000));
threadPool.shutdown();
while (!threadPool.isTerminated())
{
try {Thread.sleep(300);} catch (InterruptedException e) {{logException(e);}}
}
System.out.println("----------------------" );
System.out.println("thread operations finished, final balance : " + chuck.getBalance());
int actualBalance = (900+40+80+8000)-(1000+50+5000);
System.out.println("Validity check " + actualBalance);
}
static void logException(InterruptedException e)
{
System.out.println("###########interruptedexception#########" + e);
}
}
Below is my console output
> balance added: 80
> invoked to deduct :1000
> balance added: 8000
> invoked to deduct :5000
> invoked to deduct :50
> balance added: 900
> balance added: 40
> deducted:5000
> deducted:50
> deducted:1000
----------------------
thread operations finished, final balance : 2970
Validity check 2970
The question I have is, why the below is not printed in console output
> System.out.println("> hey I was notified for cutting amount:" + amount);
This method is written next to wait() of deduct balance method in CustomerAccount class.
答案1
得分: 0
根据 @RealSkeptic 的评论,修改了 addBalance 线程,在进入执行之前添加了休眠。在这之后,所有的 sysouts 都被执行了。
上面发布的代码的行为是,addBalance 线程会在 deductBalance 线程进入同步块之前被执行。
使用下面的方法替换 addBalance 后,输出结果发生了变化。
boolean addBalance(final int amount)
{
try {Thread.sleep(3000);} catch (InterruptedException e) {{TestWaitNotifyBasic.logException(e);}}
synchronized (this)
{
balance += amount;
notifyAll();
}
System.out.println("> balance added: " + amount);
return true;
}
方法更改后的控制台输出:
> invoked to deduct: 50
> invoked to deduct: 1000
> invoked to deduct: 5000
> balance added: 900
> balance added: 40
> hey I was notified for cutting amount: 50
> balance added: 8000
> balance added: 80
> hey I was notified for cutting amount: 5000
> deducted: 50
> hey I was notified for cutting amount: 1000
> deducted: 1000
> deducted: 5000
----------------------
线程操作已完成,最终余额: 2970
有效性检查 2970
英文:
Following @RealSkeptic's comment, modified the addBalance Thread to sleep before entering execution. Post this all the sysouts got executed
The behavior of code posted above was that the addBalance threads would get executed before the deductBalance thread entered the synchronized block.
With below method for addBalance, the ouptut changes.
boolean addBalance(final int amount)
{
try {Thread.sleep(3000);} catch (InterruptedException e) {{TestWaitNotifyBasic.logException(e);}}
synchronized (this)
{
balance += amount;
notifyAll();
}
System.out.println("> balance added: " + amount);
return true;
}
Console output post method change:
> invoked to deduct :50
> invoked to deduct :1000
> invoked to deduct :5000
> balance added: 900
> balance added: 40
> hey I was notified for cutting amount:50
> balance added: 8000
> balance added: 80
> hey I was notified for cutting amount:5000
> deducted:50
> hey I was notified for cutting amount:1000
> deducted:1000
> deducted:5000
----------------------
thread operations finished, final balance : 2970
Validity check 2970
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论