2016-09-25 88 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线程的数量,而不是使循环做新的阴影,我应该把它放在运行方法? –