2016-09-25 2 views
0

Ich arbeite an einem Projekt und ich habe zwei Threads, die zusammen laufen. Das Projekt ist eine Pseudo-Bank, und wir haben im Wesentlichen einen Einzahlungs-Thread und einen Auszahlungs-Thread. Ich habe ein Problem, bei dem die Einzahlungs-Threads zu oft ausgeführt werden und der Kontostand des Kontos steigt. (Ich wünschte, ich hätte dieses Problem in realife.) Wie kann ich die Zeit reduzieren, die ein Thread läuft?Wie reduziere ich die Zeit, die ein Thread läuft?

Hier ist meine Hauptklasse:

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


    } 


} 

Hier sind die zurückziehen und Einlagen Thread Klassen:

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) { 


     } 



    } 
} 

und schließlich ist sie die Transaktionsklasse:

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

Ich habe habe versucht, die Threads schlafen zu lassen, bevor sie den Sperrzustand erreicht haben, aber leider funktioniert es nicht.

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

Müssen Sie Threads verwenden? Wenn Sie nur versuchen, zufällige Transaktionen zu simulieren, verwenden Sie die Klasse "Random". –

+0

Ja, für die Zuweisung muss ich Threads ohne die Synchronisationsblöcke verwenden. –

Antwort

2

Das größere Problem ist, dass auf jede Iteration der while(true), Sie 7 separate Threads erstellen. Sie erzeugen hier eine unendliche Anzahl von Threads und Bankkonten.

Jedes Mal instanziert ein neues DepositThread oder WithdrawThread, sind Sie ein neues transaction Objekt, jedes mit seinem eigenen privaten Lock schaffen, die nichts effektiv synchronisiert.

public class WithdrawThread implements Runnable { 

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

    ... 
} 

Es gibt keinen ordnungsgemäß geschützten gemeinsamen Status unter Ihren Threads. Jedes WithdrawThread/DepositThread versucht nur seine eigene private Sperre über das Objekt transaction zu erwerben. Eine Lock kann nur gegenseitigen Ausschluss auf einer Ressource erzwingen, wenn alle Threads darauf zugreifen können.

Eine bessere Lösung wäre einTransaction Objekt, dessen Verweis als Parameter an jeden Thread übergeben wird.

1

Es klingt, als ob Sie zwei Threads haben möchten, die gleichzeitig laufen, ein Einzahlungs-Thread und ein Auszugs-Thread, aber das ist nicht das, was Sie haben. Stattdessen erstellt Ihre Hauptschleife drei separate Einzahlungs-Threads und vier separate Auszahlungs-Threads jedes Mal durch die Schleife, und die Schleife scheint unbegrenzt zu laufen, sodass Sie eine unbegrenzte Anzahl von Threads erstellen. Da die Einlagenfäden eine Verzögerung von 100 ms haben und die Entnahmefäden nicht, läuft ein Bündel der Abzugsfäden, dann läuft nach 100 ms ein Bündel von Einlagenfäden ab. Darüber hinaus greifen die Threads tatsächlich nicht auf einen gemeinsamen Kontostand zu.

Beginnen Sie mit dem Hauptfaden, um nur ein Abzugsgewinde und ein Ablagerungsgewinde zu erstellen und dann zu beenden. Dann legen Sie die Schleifen in die Ein- und Austrittsfäden. Das wird einige Ihrer Probleme beheben.

Nachdem Sie das getan haben, werden Sie wahrscheinlich noch andere Probleme haben, aber sie werden andere Probleme sein und Sie können sie herausfinden und sie selbst beheben. Wenn nicht, können Sie immer eine neue Frage zu ihnen stellen.

+0

yeah ich arbeite daran, die int-balance zu teilen, dann denke ich, wenn ich die x menge an threads gemacht habe, anstatt die schleife neue insitnaces zu machen, sollte ich es in die run-methode setzen? –

Verwandte Themen