Java代码semphore

时间:2016-05-19 23:06:32

标签: java semaphore

我有以下java代码。这会给每个人带来不同的输出。我必须使用信号量和互斥量,但我不知道在哪里使用。我是多线程的新手,所以有人可以告诉我这个程序中的线程在哪里。我该怎么做才能获得一致的结果

Account.java

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

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

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

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



}

请帮我解决这个问题。

2 个答案:

答案 0 :(得分:2)

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

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

[编辑]

当方法为synchronized时,运行时环境保证如果多个线程在给定对象中调用相同的方法,则只执行其中一个,其他线程一直等到完成。然后执行另一个线程,依此类推。

[EDIT2]

另外,请勿直接访问Account的数据成员。让他们private并定义synchronized getter和setter。程序中的真正问题在于传输操作:

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

这种方式不是原子的。想象一下,例如,兴趣线程在执行中的这两行之前执行,而在另一行之间执行。您将获得不同的最终结果。要解决此问题,请将以下方法添加到Account类:

public synchronized void transfer (Account to, double amount) {
     this.withdraw (amount);
     to.deposit(amount);
}

并通过此调用替换两行:

  synchronized(myAccount2) {
       myAccount1.transfer(myAccount2, myAmount);
  }

synchronized方法的调用周围添加transfer块的原因是您需要获取两个对象的两个锁才能执行传输。 synchronized(myAccount2)获取myAccount2的锁定,transfer的调用获取myAccount1的锁定,方法transfer已同步。

[EDIT3]

您的计划中还存在一个概念性问题。您正在计算两个帐户的利益并在它们之间转移资金,所有这些都在并行线程中。因此,如果您首先转移资金然后计算利息,或者如果您首先计算利息然后转移资金,那么产生不同结果是正常的。尝试手工完成数学运算。如果您想对操作进行排序,请不要使用线程,只需按顺序调用方法

答案 1 :(得分:0)

您可以将thread.join()用于checkInterest和saveInterest。因此,当两个结束时,转移开始

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

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

transfer.start();