首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java代码符号

Java代码符号
EN

Stack Overflow用户
提问于 2016-05-19 23:06:31
回答 2查看 261关注 0票数 1

我有下面的java代码。这给出了不同的输出在每个。我想我必须使用信号量和互斥量,但我不知道该在哪里使用。我对多线程很陌生,所以有人能告诉我这个程序中的线程在哪里。我该怎么做才能得到一致的结果

Account.java

代码语言:javascript
复制
package banking;

public class Account {
    final String accountHolder;
    final String accountType;
    double balance=0;

    public Account(String name, String type,double credit) {
        this.accountHolder = name;
        this.accountType = type;        
        this.balance=credit;
    }

    public void deposit(double credit) {
        balance += credit;
    }

    public void withdraw(double credit) {
        balance -= credit;
    }

    public void addinterest(double rate) {
        balance *= (100+rate)/100.0;
    }

}

Banking.java

代码语言:javascript
复制
package banking;

public class Banking {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws InterruptedException {
        System.out.println("Application started");

        Account savings  = new Account("Pete","Super Saver",1000);
        Account checking = new Account("Pete","Free Checking",1000);

        System.out.println("\nBeginning of month");
        System.out.println(savings.accountType + ":\t"+ savings.balance);
        System.out.println(checking.accountType + ":\t"+ checking.balance);
        System.out.println("Total before \t"+ (checking.balance+savings.balance));


        Interest checkInterest = new Interest(checking, -10);        
        Interest saveInterest = new Interest(savings, 10);   
        Transfer transfer = new Transfer(savings,checking,100);  


        checkInterest.start();
        saveInterest.start(); 
        transfer.start();


        Thread.sleep(520);
        System.out.println("\nEnd of month");
        System.out.println(savings.accountType + ":\t"+ savings.balance);
        System.out.println(checking.accountType + ":\t"+ checking.balance);
        System.out.println("Total  after \t"+ (checking.balance+savings.balance));
        System.out.println("Main thread finished");
    }
}

Interest.java

代码语言:javascript
复制
package banking;

import java.util.logging.Level;
import java.util.logging.Logger;


class Interest extends java.lang.Thread {
    final Account myAccount;
    double myRate;

    public Interest(Account account, double rate) {
          this.myAccount=account;
          this.myRate = rate;
          setName("Interest");
    }

    @Override
    public void run() {

         System.out.println("Interest this month on "+  myAccount.accountType + ":\t" + myAccount.balance*myRate/100.0);
         myAccount.addinterest(myRate);

          //System.out.println(getName() + " to account " + myAccount.accountType + " successfully applied");
    }



}

Transfer.java

代码语言:javascript
复制
package banking;

import java.util.logging.Level;
import java.util.logging.Logger;

class Transfer extends java.lang.Thread {    
    final Account myAccount1;
    Account myAccount2;
    double myAmount;

    public Transfer(Account account1,Account account2, double amount) {
          this.myAccount1=account1;
          this.myAccount2=account2;
          this.myAmount = amount;
          setName("Transfer");
    }

    @Override
    public void run() {


        myAccount1.withdraw(myAmount);
        myAccount2.deposit(myAmount);

        System.out.println(getName() + " from " + myAccount1.accountType + " to " + myAccount2.accountType + " successfully applied");
    }



}

请帮我解决这个问题。

EN

回答 2

Stack Overflow用户

发布于 2016-05-19 23:13:39

不需要信号量。只需在synchronized类中的每个方法之前添加Account。例如:

代码语言:javascript
复制
public synchronized void deposit(double credit) {
    balance += credit;
}

编辑

当一个方法是synchronized时,运行时环境保证如果多个线程在给定对象中调用相同的方法,那么它们中只有一个会执行,而其他线程则会等待它完成。然后执行另一个线程,以此类推。

EDIT2

另外,不要直接访问Account的数据成员。使它们成为private,并定义synchronized getter和setter。您的程序中真正的问题在于传输操作:

代码语言:javascript
复制
    myAccount1.withdraw(myAmount);
    myAccount2.deposit(myAmount);

从这种角度来说,它不是原子的。例如,假设兴趣线程在执行中在这两行之前执行,在它们之间执行另一行。你会得到不同的最终结果。要解决这个问题,请向Account类添加以下方法:

代码语言:javascript
复制
public synchronized void transfer (Account to, double amount) {
     this.withdraw (amount);
     to.deposit(amount);
}

并将这两行替换为:

代码语言:javascript
复制
  synchronized(myAccount2) {
       myAccount1.transfer(myAccount2, myAmount);
  }

在调用synchronized方法时添加transfer块的原因是,为了执行传输,需要获取两个对象的两个锁。synchronized(myAccount2)获得myAccount2的锁,而transfer的调用获得myAccount1的锁,因为方法transfer是同步的。

EDIT3

在您的程序中也存在一个概念问题。你在计算两个帐户的利息,并在它们之间转账,所有这些都是并行的。所以,如果你先转移钱,然后计算利息,或者你先计算利息,然后再转帐,就会有不同的结果。试着用手算一下。如果您想对操作进行排序,不要使用线程,只需按顺序调用方法

票数 2
EN

Stack Overflow用户

发布于 2016-05-21 23:43:13

您可以将thread.join()用于checkInterest和saveInterest。所以当这两件事结束时,转移就开始了。

代码语言:javascript
复制
checkInterest.start();
saveInterest.start(); 

checkInterest.join();
saveInterest.join();

transfer.start();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37335462

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档