【问题标题】:Issue in Thread Pooling线程池中的问题
【发布时间】:2017-07-08 11:34:52
【问题描述】:

注意:线程号 1 = 所有者 1 -> 执行 10 个事务
线程 2 = Owner 2 -> 执行 10 个事务

问题:在输出中:

Owner: 1   transaction: 2
Owner: 1   transaction: 1
credit: $46 credit: $30  balance: $146
 balance: $130

交易 2 后余额应为 176 美元。线程池肯定有问题。我尝试了很多,但无法达到所需的解决方案。任何帮助都是不言而喻的。

输出

跑步: 初始余额:100 美元 所有者:1 笔交易:1 所有者:1 交易:2 贷方:46 美元贷方:30 美元余额:146 美元 余额:$130 所有者:2 交易:1 所有者:2 交易:2 借方:46 美元借方:30 美元借方完成借方完成余额:100 美元余额:100 美元 所有者:1 笔交易:3 信用:75 美元所有者:1 次交易:4 余额:175美元 信用:47 美元所有者:2 次交易:3 余额:147美元 所有者:2 交易:4 借方:47 美元借方:75 美元借方完成借方完成余额:100 美元余额:100 美元 所有者:1 笔交易:5 信用:57 美元所有者:1 次交易:6 余额:157美元 信用:13 美元所有者:2 次交易:5 余额:$113 借记:57 美元 借记完成 所有者:2 次交易:6 余额:100 美元借记:13 美元借记完成余额:100 美元所有者:1 笔交易:7 信用:84 美元所有者:1 笔交易:8 余额:184 美元 信用:95 美元所有者:2 次交易:7 余额:195美元 所有者:2 交易:8 借方:84 美元借方完成借方:95 美元借方完成余额:100 美元余额:100 美元 所有者:1 笔交易:10 笔信用:96 美元余额:196 美元 所有者:1 笔交易:9 所有者:2 交易:10 贷方:20 美元借方:96 美元借方完成余额:120 美元 余额:100 美元 所有者:2 交易:9 借记:$20 借记完成余额:$100B

银行

public class Bank{

private BankAccount bankAccount = new BankAccount(100);

public void displayInitialBalance(){
    System.out.println("Initial Balance:"+getBankAccount());
}

/**
 * @return the bankAccount
 */
public BankAccount getBankAccount() {
    return bankAccount;
}

/**
 * @param bankAccount the bankAccount to set
 */
public void setBankAccount(BankAccount bankAccount) {
    this.bankAccount = bankAccount;
}

public static void main(String[] args){
    BankAccount bankAccount = new BankAccount(100);
    System.out.println("Initial Balance: $"+bankAccount.getCurrentBalance());
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    for(int count = 1; count<=10; count++){
        Runnable runnable = new Owner(count);
        executorService.execute(runnable);
    }
    executorService.shutdown();
    while(!executorService.isTerminated()){
    }
    System.out.println("All Transactions Done");
}

}


银行账户

public class BankAccount {

private int currentBalance;

public BankAccount(int initialBalance){
    this.currentBalance = initialBalance;
}

synchronized public void credit(int amount){
    setCurrentBalance(currentBalance + amount);
    System.out.print("credit: $"+amount+"\t");
    System.out.println(" balance: $"+getCurrentBalance());
}

synchronized public void debit(int amount){
    if(getCurrentBalance() >= amount){
        setCurrentBalance(currentBalance - amount);
        System.out.print(" debit: $"+amount);
        System.out.print(" Debit Done" +"\t");                
        System.out.print(" Balance: $"+getCurrentBalance());            
    }
    else{
        System.out.print("Insufficient Balance"+"\t");
        System.out.println("Balance: $"+getCurrentBalance());
    }
}

/**
 * @return the currentBalance
 */
public int getCurrentBalance() {
    return currentBalance;
}

/**
 * @param currentBalance the currentBalance to set
 */
public void setCurrentBalance(int currentBalance) {
    this.currentBalance = currentBalance;
}
}    


所有者

public class Owner implements Runnable{

public int transactionCount = 0;
public int amount = 0;

private BankAccount bankAccount = new  BankAccount(100);

public Owner(int transactionCycle){
    this.transactionCount = transactionCycle;
}

public Owner(int transactionId, BankAccount bankAccount){
    this.bankAccount = bankAccount;
    this.transactionCount = transactionId;
}

@Override
public void run() {
   try{
       amount = (int)(Math.random() * 100 + 10);
       Thread call = new Thread();
       call.start();
       Thread.currentThread().setName("Owner: 1 "+"  transaction: "+transactionCount);
       (transactionCount)++;
       System.out.println(Thread.currentThread().getName());
       getBankAccount().credit(amount);
       Thread.currentThread().setName("Owner: 2 "+"  transaction: "+ --(transactionCount));
       (transactionCount)++;
       System.out.println(Thread.currentThread().getName());
       getBankAccount().debit(amount);
   }catch(UnsupportedOperationException e){
       e.printStackTrace();
   } 

}

/**
 * @return the bankAccount
 */
public BankAccount getBankAccount() {
    return bankAccount;
}

/**
 * @param bankAccount the bankAccount to set
 */
public void setBankAccount(BankAccount bankAccount) {
    this.bankAccount = bankAccount;
}

}

【问题讨论】:

  • 你有一个你从不实例化的类Bank,不可编译的代码,一个什么都不做的Thread call,即使你在不同的线程中运行该代码,同步也不充分。 BankAccount 实例永远不会从多个线程直接访问,但它是部分(!)同步的,Owner 实例从多个线程访问的(或将是),但它没有同步方法。除其他事项外(如修复编译器错误),我建议制作Owner#bankAccount final 并开始构建。不是现在的两倍。
  • 您对 Thread 调用是正确的,我已将其删除。但我不明白的是,我将BankAccount instance 更改为final 并从Constructor 调用它一次,但同步仍然出错private final BankAccount bankAccount; public Bank(){ bankAccount = new BankAccount(100); }
  • 现在所有代码都工作正常,执行正确的计算只有一个问题出现在output format Owner: 1 transaction: 1 credit: $10 Balance: $110 Owner: 2 transaction: 1 debit: $48 Debit Done ?? Owner: 1 transaction: 2 Balance: $62 credit: $88 Balance: $150 Owner: 2 transaction: 2 debit: $85 Debit Done Balance: $65 我把**放在哪里?? Balance $62 必须在那里打印
  • “线程池中一定有问题” -- 极不可能,问题很可能出在您的代码中。请访问help center,阅读How to Ask,也阅读Why is “Can someone help me?” not an actual question?
  • 我也在努力寻找解决方案。

标签: java multithreading threadpool


【解决方案1】:

您在 Bank.main() 中创建新的 Owner 实例而没有传递 BankAccount,因此每个 Owner 对象都在不同的 BankAccount 实例上运行

【讨论】:

  • Runnable runnable = new Owner(count,bankAccount);Owner() 代码中提供 bankAccount 作为参数后工作正常。但是输出格式会很混乱,因为 outputOwner: 1 transaction: 1 Owner: 1 transaction: 2 credit: $49 balance: $149 credit: $29 Owner: 2 transaction: 1 balance: $178 Owner: 2 transaction: 2 debit: $87 Debit Done Balance: $91 debit: $24 Debit Done Balance: $67
  • ** 输出应该是这样的** Owner: 1 transaction: 1 Owner: 1 transaction: 2 credit: $49 balance: $149 credit: $29 balance: $178 所以肯定有一些我尝试了很多无法捕捉到的问题是同步
【解决方案2】:

做了很多尝试,最后得到了所需的输出

已完成更改

银行账户

private int currentBalance = 0; // set default value of int
public void credit(int amount){
    System.out.print(" credit: $"+amount+"\t");
}

public Boolean debit(int amount){
    if(getCurrentBalance() >= amount){
        return true;
    }
    else
        return false;
}

银行
How to wait for all threads to finish, using ExecutorService?

ma​​in方法的for循环内部

Runnable runnable = new Owner(id,bankAccount);
bankAccount.getCurrentBalance(); // To print each thread transaction balance
try {
        executorService.awaitTermination(Long.MAX_VALUE,  TimeUnit.NANOSECONDS); // instead of Terminate use awaitTermination method for each thread 
    } catch (InterruptedException e) {
        e.printStackTrace();
    }    

所有者

try{
       amount = (int)(Math.random() * 100 + 10);
       Thread.currentThread().setName(" Owner: 1 "+"  transaction: "+transactionCount);
       (transactionCount)++;
       System.out.print(Thread.currentThread().getName()+"\n");
       getBankAccount().credit(amount);
       bankAccount.setCurrentBalance(getBankAccount().getCurrentBalance() + amount);
       System.out.print("Balance: $"+bankAccount.getCurrentBalance());
       amount = (int)(Math.random() * 100 + 10);
       Thread.currentThread().setName(" Owner: 2 "+"  transaction: "+ --(transactionCount));
       System.out.print(Thread.currentThread().getName()+"\n");
       (transactionCount)++;
       getBankAccount().getCurrentBalance();
       Boolean isDebit = getBankAccount().debit(amount);
       if(isDebit){
           try {
                bankAccount.setCurrentBalance(getBankAccount().getCurrentBalance() - amount);
                System.out.println(" debit: $"+amount);
                System.out.print(" Debit Done" +"\t");
                System.out.println(" Balance: $"+bankAccount.getCurrentBalance());
           } catch (SecurityException ex) {
                Logger.getLogger(Owner.class.getName()).log(Level.SEVERE, null, ex);
           }
        }else{
                System.out.println("Insufficeint Balance");
        }

   }catch(UnsupportedOperationException e){
       e.printStackTrace();
   } 

【讨论】:

  • 您的 BankAccount#credit 和 debit 方法不会改变余额。您向我们展示的任何其他内容都不会使用您的 Bank 类。您正在使用 Boolean ,您应该使用 boolean 来声明不必要的变量。您有不同类的实例引用的不相关的 BankAccount 实例。出于工程目的,您随意且频繁地更改线程名称。您没有显示 Owner 方法是同步的。你拼错了“不足”。您在打印中使用 \n 而不仅仅是 println。 ..
  • Credit & Debit 方法改变余额两个交易输出附加Initial Balance:$100 Owner: 1 transaction: 2 credit: $38 Balance: $138 Owner: 2 transaction: 2 debit: $79 Debit Done Balance: $59 Owner: 1 transaction: 3 credit: $35 Balance: $94 Owner: 2 transaction: 3 debit: $39 Debit Done Balance: $55
  • 是的,我相信我的方法在更改线程方面并不完美,但剩下的 \n 而不是仅用于格式化我的输出的 println。在开始时,我已经同步了 debit()credit 方法,但它们不工作,所以我尝试在没有它的情况下工作并且工作正常。
猜你喜欢
  • 2020-10-02
  • 1970-01-01
  • 1970-01-01
  • 2011-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-23
相关资源
最近更新 更多