代码中 wait 方法之后为什么没有调用?

huangapple go评论59阅读模式
英文:

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(&quot;&gt; invoked to deduct :&quot; + amount);
synchronized (this)
{
while (balance &lt;= amount)
{
try {wait(); } catch (InterruptedException e) {TestWaitNotifyBasic.logException(e);}
System.out.println(&quot;&gt; hey I was notified for cutting amount:&quot; + amount);
}
balance-= amount;
}
System.out.println(&quot;&gt; deducted:&quot; + amount);
return true;
}
boolean addBalance(final int amount)
{
synchronized (this)
{
balance += amount;
notifyAll();
}
System.out.println(&quot;&gt; balance added: &quot; + 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&lt;Runnable&gt; addBalance = (amount) -&gt; { return () -&gt; chuck.addBalance(amount);};
IntFunction&lt;Runnable&gt; deductBalance = (amount) -&gt; { return () -&gt; 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(&quot;----------------------&quot; );
System.out.println(&quot;thread operations finished, final balance : &quot; + chuck.getBalance());
int actualBalance = (900+40+80+8000)-(1000+50+5000);
System.out.println(&quot;Validity check &quot; + actualBalance);
}
static void logException(InterruptedException e)
{
System.out.println(&quot;###########interruptedexception#########&quot; + e);
}
}

Below is my console output

&gt; balance added: 80
&gt; invoked to deduct :1000
&gt; balance added: 8000
&gt; invoked to deduct :5000
&gt; invoked to deduct :50
&gt; balance added: 900
&gt; balance added: 40
&gt; deducted:5000
&gt; deducted:50
&gt; 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(&quot;&gt; balance added: &quot; + amount);
return true;
}

Console output post method change:

&gt; invoked to deduct :50
&gt; invoked to deduct :1000
&gt; invoked to deduct :5000
&gt; balance added: 900
&gt; balance added: 40
&gt; hey I was notified for cutting amount:50
&gt; balance added: 8000
&gt; balance added: 80
&gt; hey I was notified for cutting amount:5000
&gt; deducted:50
&gt; hey I was notified for cutting amount:1000
&gt; deducted:1000
&gt; deducted:5000
----------------------
thread operations finished, final balance : 2970
Validity check 2970

huangapple
  • 本文由 发表于 2020年10月4日 18:25:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/64193485.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定