2016-09-25 50 views
0

我正在一個項目上工作,我有兩個線程一起運行。該項目是一個模擬銀行,基本上,我們有一個存款線程和一個撤回線程。我遇到的問題是存款線索經常運行,導致銀行賬戶的餘額上升。 (我希望我在真正的生活中遇到過這個問題。)我如何減少線程運行的時間?如何減少線程運行的時間量?

這裏是我的主類:

package bankexample; 
import bankexample.depositThread; 

public class BankExample { 

     public static int balance =0 ; 



    public static void main(String[] args) { 
     System.out.println("Deposit Thread   Withdrawl Thread   Balance \n"); 
     System.out.println("--------------   -----------------   --------"); 
     while (true){ 
     Thread d1 = new Thread(new depositThread(1)); 
     Thread d2 = new Thread(new depositThread(2)); 
     Thread d3 = new Thread(new depositThread(3)); 
     Thread w1 = new Thread(new WithdrawThread(1)); 
     Thread w2 = new Thread(new WithdrawThread(2)); 
     Thread w3 = new Thread(new WithdrawThread(3)); 
     Thread w4 = new Thread(new WithdrawThread(4)); 

     d1.start(); 
     d2.start(); 
     d3.start(); 
     w1.start(); 
     w2.start(); 
     w3.start(); 
     w4.start(); 
     } 


    } 


} 

這裏的退出,存款線程類:

package bankexample; 

/** 
* 
* @author KJ4CC 
*/ 
public class WithdrawThread implements Runnable { 
    transaction withdraw = new transaction(); 
    int threadNum; 
    public WithdrawThread(int num){ 
     threadNum = num; 
    } 

    public void run(){ 
     withdraw.withdraw(threadNum); 
    } 
} 

--------------------------- 
package bankexample; 
import bankexample.transaction; 

/** 
* 
* @author KJ4CC 
*/ 
public class depositThread implements Runnable { 
    transaction startThread = new transaction(); 
    public static int balance; 
    int threadNum; 
    public depositThread(int num){ 
     threadNum = num; 

    } 
    @Override 
    public void run(){ 


     try { 
       Thread.sleep(100); 
       startThread.deposit(threadNum); 

     } catch (Exception e) { 


     } 



    } 
} 

,最後她是事務類:

package bankexample; 
import java.util.Random; 
import java.util.concurrent.locks.ReentrantLock; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.Condition; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
/** 
* 
* @author KJ4CC 
*/ 
public class transaction extends BankExample { 

    private Lock accessLock = new ReentrantLock(); 
    private Condition cond = accessLock.newCondition(); 
    private boolean occupied = false; 
    Random rand = new Random(); 

    public void deposit(int threadNum) throws InterruptedException{ 
     //random amount for amount to deposit into bank mod 200 
     int amount = rand.nextInt(200); 

     //locks the thread 
     //System.out.println("Balance before Deposit " + balance); 
     accessLock.lock(); 
     try { 
      //System.out.println(getBalance.getbalance()); 
      //adds the amount to the balance. 
      if (occupied == false){ 
      occupied = true; 
      balance = (balance + amount); 
      //outputs to terminal 
      System.out.println("Thread " + threadNum + " Deposits " + amount + "\t\t\t\t Balance is " + balance); 
      occupied = false; 
      Thread.sleep(10000); 
      //signals any awiting widthdraw threads 
      cond.signal(); 

      } 
     } finally { 
      //unlocks thread 

      accessLock.unlock(); 
     } 

    } 
    public void withdraw(int threadNum){ 
     //getting a random amount mod50 
     int amount = rand.nextInt(50); 

     //locking the thread 
     accessLock.lock(); 
     try { 
      //test print out 


      //checks to see if the amount is less than the balance 
      if (amount < balance && occupied == false) { 
       occupied = true; 
       // System.out.println("Balance before withdraw " + balance); 
       balance = (balance - amount); 

       System.out.println("\t\t\tThread " + threadNum + " withdrawls " + amount + "\t Balance is " + balance); 
       cond.signalAll(); 
       occupied = false; 
       //if it isnt we can not make a withdraw so we have to wait for a deposit 
      } else { 

       System.out.println("\t\t\tThread " + threadNum + " Failed to withdrawl " + amount + "\t Balance is " + balance); 
       cond.await(); 

      } 
      //unlock the thread 
     } catch (InterruptedException ex) { 
      Logger.getLogger(transaction.class.getName()).log(Level.SEVERE, null, ex); 
     } finally { 
      accessLock.unlock(); 
     } 
    } 
} 

我有試圖在線程遇到鎖定狀態之前讓它們睡眠,但不幸的是,它不起作用。

Here is a sample from the output: 
Deposit Thread   Withdrawl Thread   Balance 

--------------   -----------------   -------- 
      Thread 1 Failed to withdrawl 4 Balance is 0 
      Thread 2 Failed to withdrawl 49 Balance is 0 
      Thread 3 Failed to withdrawl 21 Balance is 0 
      Thread 4 Failed to withdrawl 13 Balance is 0 
      Thread 1 Failed to withdrawl 30 Balance is 0 
      Thread 2 Failed to withdrawl 15 Balance is 0 
      Thread 3 Failed to withdrawl 18 Balance is 0 
      Thread 4 Failed to withdrawl 25 Balance is 0 
      Thread 2 Failed to withdrawl 27 Balance is 0 
      Thread 1 Failed to withdrawl 9 Balance is 0 
      Thread 3 Failed to withdrawl 0 Balance is 0 
      Thread 4 Failed to withdrawl 21 Balance is 0 
      Thread 1 Failed to withdrawl 31 Balance is 0 
      Thread 2 Failed to withdrawl 32 Balance is 0 
      Thread 3 Failed to withdrawl 47 Balance is 0 
      Thread 4 Failed to withdrawl 8 Balance is 0 
      Thread 1 Failed to withdrawl 22 Balance is 0 
      Thread 2 Failed to withdrawl 38 Balance is 0 
      Thread 3 Failed to withdrawl 43 Balance is 0 
      Thread 4 Failed to withdrawl 2 Balance is 0 
      Thread 1 Failed to withdrawl 19 Balance is 0 
      Thread 2 Failed to withdrawl 39 Balance is 0 
      Thread 3 Failed to withdrawl 43 Balance is 0 
      Thread 4 Failed to withdrawl 48 Balance is 0 
      Thread 1 Failed to withdrawl 45 Balance is 0 
      Thread 3 Failed to withdrawl 45 Balance is 0 
      Thread 2 Failed to withdrawl 25 Balance is 0 
      Thread 4 Failed to withdrawl 21 Balance is 0 
Thread 2 Deposits 188    Balance is 188 
Thread 3 Deposits 128    Balance is 316 
Thread 2 Deposits 54     Balance is 370 
Thread 1 Deposits 123    Balance is 493 
Thread 3 Deposits 59     Balance is 552 
      Thread 1 withdrawls 38 Balance is 514 
      Thread 2 withdrawls 35 Balance is 479 
      Thread 3 withdrawls 40 Balance is 439 
      Thread 4 withdrawls 5 Balance is 434 
Thread 1 Deposits 179    Balance is 613 
Thread 1 Deposits 108    Balance is 1027 
Thread 2 Deposits 56     Balance is 919 
Thread 1 Deposits 96     Balance is 863 
Thread 2 Deposits 101    Balance is 767 
Thread 3 Deposits 149    Balance is 1176 
Thread 3 Deposits 53     Balance is 666 
Thread 2 Deposits 67     Balance is 1277 
Thread 1 Deposits 108    Balance is 1385 
Thread 3 Deposits 34     Balance is 1277 
Thread 2 Deposits 69     Balance is 1466 
Thread 3 Deposits 49     Balance is 1561 
      Thread 4 withdrawls 32 Balance is 1529 
Thread 1 Deposits 12     Balance is 1561 
Thread 2 Deposits 46     Balance is 1561 
Thread 1 Deposits 99     Balance is 15 
+0

您是否必須使用線程?如果你只是想模擬一些隨機事務發生,那麼使用Random類。 –

+0

是的,每次分配我必須使用線程與同步塊。 –

回答

2

更大的問題是,在while(true)的每次迭代,要創建7個單獨的線程。你基本上在這裏產生無數的線程和銀行賬戶。

每次實例化一個新DepositThreadWithdrawThread,要創建一個新的transaction對象,每個都有自己的私人Lock,有效地同步什麼。

public class WithdrawThread implements Runnable { 

    //creates a new Lock per *Thread* 
    transaction withdraw = new transaction(); 

    ... 
} 

在你的任何線程中沒有適當保護的共享狀態。每個WithdrawThread/DepositThread僅嘗試通過transaction對象嘗試獲取其自己的私人鎖對象。如果所有線程都可以訪問,則Lock只能對資源實施互斥。

一個更好的解決辦法是有一個Transaction對象,其引用作爲參數給每個線程被傳遞。

1

這聽起來像你打算有兩個線程同時運行,一個存款線程和一個提款線程,但這不是你所擁有的。相反,您的主循環每次創建三個單獨的存儲線程和四個單獨的提取線程,並且循環似乎無限期運行,因此您創建的線程數量不受限制。由於存款線程有100ms的延遲,並且退出線程沒有,一堆退出線程運行,然後100ms後有一堆存款線程運行。此外,這些線程實際上並未訪問通用的「銀行賬戶」餘額。

首先,讓主線程創建一個退出線程和一個存款線程,然後退出。然後將這些循環放入存取線程中。這將解決你的一些問題。

完成這些之後,您可能還會遇到其他問題,但它們會有不同的問題,您可能會發現並自行修復它們。如果沒有,你可以隨時在他們身上發佈一個新問題。

+0

是的我正在努力獲得int平衡分享,然後我認爲如果我提出了x線程的數量,而不是使循環做新的陰影,我應該把它放在運行方法? –