ShutDownHook in einer Multithread-Anwendung

  • Ich habe eine Anwendung, die in der Hauptmethode hundert Threads erzeugt (sagen wir, wir simulieren hundert Konten). Ich experimentiere damit, und ich möchte, dass es nur gedruckt wird, wenn es mit Control-C unterbrochen wird.

    Ich habe gelesen, dass Sie dies mit ShutDownHooks tun können Methode:

     Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                                 System.out.println("Terminating");
                            }
            });
     

    Beim Ausführen wird jedoch nichts gedruckt.

    Könnten Sie mir bitte eine Anleitung geben, wo ich falsch liege (alle Threads sind in einer for-Schleife deklariert und beginnen mit dem Aufruf ihrer Startmethode)?

    Grüße , George

    BEARBEITEN: Den Code finden Sie unten:

    Bankklasse:

     public class Bank {
     private final double[] accounts;
       public Bank(int n, double initialBalance) {
        accounts = new double[n];
        for (int i=0; i < accounts.length;i++) {
            accounts[i] = initialBalance;
        }
    }
        public double getTotalBalance() {
            double sum = 0.0;
            for (int i=0; i < accounts.length; i++) {
                sum += accounts[i];
            }
            return sum;
        }
        public synchronized void transfer(int fa, int ta, double amt) throws InterruptedException{
            System.out.print(Thread.currentThread());
            if (accounts[fa] < amt){
                            wait();
                        }
            accounts[ta] -= amt;
            System.out.println("Transfer of amount: " + amt + " from: " + fa + " Transfer to: " + ta);
            accounts[fa] += amt;
            System.out.println("Total Balance: " + getTotalBalance());
            notifyAll();
    
    }
    public int size() {
        return accounts.length;
    }
    public double[] getAccounts(){
        return accounts;
    }
    
    }
     

    Banktest-Klasse:

     public class BankTest {
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
                Bank b = new Bank(100,1000);
        int i;
            long timeStart = System.currentTimeMillis();
            long j = System.currentTimeMillis();
    
    
    
    
    
                for (i=0; i < b.size(); i++) {
            TransferRunnable tr = new TransferRunnable(b, i, 1000,j);
            Thread t = new Thread(tr);
            t.start();
    
        }
               Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                             System.out.println("Terminating");
                        }
        });
    
    
            }
    
    
        }
     
    <|

    TransferRunnable-Klasse:

     public class TransferRunnable implements Runnable {
    private Bank b;
    private int fromAccount;
    private double maxAmount;
    private final int DELAY = 40;
    private long timeStart;
    public TransferRunnable(Bank b, int from, double max, long timems) {
        this.b = b;
        fromAccount = from;
        maxAmount = max;
            timeStart = timems;
    }
    @Override
    public void run() {
    
            try {
            while (true) {
                int ta = (int) (b.size() * Math.random());
                double amount =  maxAmount * Math.random();
                        double[] acc = b.getAccounts();
                        b.transfer(fromAccount,ta,amount);
                Thread.sleep((int) (DELAY*Math.random()));
            }
        }
            catch (InterruptedException e) {
    
            }
    
        }
    
    }
     
    23 November 2011
    user998388
2 answers
  • Wird bei der Ausführung gedruckt. Sie könnten am Ende der run () - Methode jedoch System.out.flush(); hinzufügen. Dadurch wird sichergestellt, dass die Ausgabe sofort gedruckt wird.

    22 November 2011
    Maarten BodewesSri Sankaran
  • Wie andere gesagt haben, sollte dies einfach funktionieren. Welches Betriebssystem verwendest du? Es kann sein, dass CTRL+C den Prozess vollständig beendet, anstatt ihn zum Herunterfahren aufzufordern (z. B. SIGKILL vs SIGINT). Können Sie überprüfen, welches Signal Sie den Java-Prozess senden?

    Als letzten Ausweg könnten Sie folgendes Java-Bit ausprobieren:

     if (FileDescriptor.out.valid()) {
        FileDescriptor.out.sync();
    }
     

    Ich vermute, dass dies jedoch keinen Unterschied macht!

    22 November 2011
    Muel