2017-05-03 50 views
1

这是与我以前提出的问题相同的代码,但解决了不同的问题。基本上,我试图用两个线程来建立银行账户,每个线程代表账户的用户。用户将随机存取20美元。一次运行一个线程(而不是并行)

但是,这两个线程并行运行,并且取款/存款同时发生我想限制两个线程,以便它在执行自己的run方法之前等待其他线程完成。

下面列出的是代码。

创建线程类

import java.util.Random; 
import java.util.concurrent.atomic.AtomicInteger; 

public class BankAccount extends Thread{ 
public static double balance = 1000; 
public String threadName; 

BankAccount(String name){ 
    threadName = name; 
} 
public void run(){ 
    System.out.println(threadName + "account initiated."); 
    for(int i = 0; i < 10; i++){ 
     try{ 
      Random rand = new Random(); 
      int num = rand.nextInt(2) + 1; 
      if(num == 1){ 
       Thread.sleep(200); //0.2 seconds to deposit 
       System.out.println(threadName + " is depositing 20$ in the bank."); 
       balance += 20; 
       System.out.println("The new balance is " + balance + "dollars"); 
      } 
      else{ 
       Thread.sleep(500); //half a second to withdraw 
       System.out.println(threadName + " is withdrawing 20$ from the bank."); 
       balance -= 20; 
       System.out.println("The new balance is " + balance + "dollars."); 
       } 
     } 
     catch(InterruptedException e){ 
      System.out.println("Process terminated."); 
      } 
     } 
    } 
} 

线程驱动程序类

public class BankAccountSimDriver { 
    public static void main(String[] args){ 
    Thread user1 = new BankAccountSIm("user1"); 
    Thread user2 = new BankAccountSIm("user2"); 

    user1.start(); 
    user2.start(); 
    } 
} 

当前输出:

user1 initiated. 
user2 initiated. 
user1 is depositing 20$ in the bank. 
user2 is depositing 20$ in the bank. 
The new balance is 1020.0 dollars 
The new balance is 1040.0 dollars 
user2 is depositing 20$ in the bank. 
The new balance is 1060.0 dollars 
user1 is withdrawing 20$ from the bank. 
The new balance is 1040.0 dollars. 

目前,user1和user2在同一时间运行。我想编辑的代码,这样只有一个用户可以存入/收回在时间(由睡眠()时间间隔指示)

所以理想的输出:

user1 initiated. 
//wait 0.2 seconds 
user1 is depositing 20$ in the bank. 
The new balance is 1020.0 dollars 
user2 initiated. 
//wait 0.2 seconds 
user2 is depositing 20$ in the bank. 
The new balance is 1040.0 dollars 
//wait 0.5 seconds 
user1 is withdrawing 20$ from the bank. 
The new balance is 1020.0 dollars. 
... 
+2

为什么你使用线程,如果你不想让它们同时运行? –

+0

你正在做一个线程的存款和提款基于随机值。那么为什么你要开始第二个线程user2.start() –

+0

我使用线程来模拟两个不同的人在一个帐户上执行操作,一次一个。是否有更简单或有效的替代方案? (Java的新手,你可以知道) –

回答

2

你需要的是要管理对balance的并发访问,而不是序列化线程,至少需要序列化访问balance。有很多方法可以解决这个问题。基本上,你需要一个应该用于让只有一个线程做balance修改,另一个被阻止,直到其他释放锁。

首先你需要分开BanckAccount及其用户。

class BankAccount { ... } 

class User implements Runnable { 
    private BankAccount account; 
    public User(BankAccount account) { 
     this.account = account; 
    } 
    public void run() { 
     // do something... 
    } 
} 

class Test { 
    public static void main(String []a) { 
     // One account 
     BankAccount a = new BankAccount(); 
     // Shared by 2 users 
     User user1 = new User(a); 
     User user2 = new User(a); 
     // Make users behave concurrently 
     Thread t1 = new Thread(user1); 
     Thread t2 = new Thread(user2); 
     t1.start(); 
     t2.start(); 
     // Wait 'til the end of the users activity 
     t1.join(); 
     t2.join(); 
    } 
} 

现在如何管理来自用户的同一银行帐户的并发访问?

class BankAccount { 
    private int balance; 
    public BankAccount(int initialBalance) { 
     balance = initialBalance; 
    } 
    public synchronized int deposit(int amount) { 
     balance += amount; 
     return balance; 
    } 
    public synchronized int withdraw(int amount) { 
     balance -= amount; 
     return balance; 
    } 
} 

这样做可以确保没有两个线程可以在同一时间内的方法标记​​,因此没有两个线程可以修改的平衡:您可以通过BankAccount方法​​使用BankAccount对象作为隐含锁同一时间。

但是......(并发导致细微的问题)......它可能发生,每个线程使用的balance缓存副本所以它一般更适合那场标记为volatile

private volatile int balance; 

请注意,在这种简单的情况下,有些事情可能会被简化,但我试图告诉你什么是问题以及如何解决问题。还要注意的是,即使这个代码可能会导致奇怪的输出,但保证是平衡是正确的(挖掘并发,现在)。