ShutDownHook в многопоточном приложении

У меня есть приложение, которое в своем основном методе порождает сотню потоков (скажем, мы имитируем сотню учетных записей). Я экспериментирую с этим, и я хотел бы, чтобы он просто печатал, прерывая работу с помощью Control-C.

Я читал, что вы можете сделать это с помощью ShutDownHooks, поэтому я добавил следующее в свой основной метод:

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

Однако, когда я запускаю его, ничего не печатается.

Не могли бы вы подсказать мне, где я ошибаюсь (все потоки объявляются в цикле for и начинаются с вызова их метода start)?

С уважением, Джордж

РЕДАКТИРОВАТЬ: Пожалуйста, смотрите ниже код:

Класс банка:

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:

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:

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

        }

    }

}

person user998388    schedule 21.11.2011    source источник
comment
Как сказано в ответе на мой ответ, можете ли вы указать особенности системы выполнения?   -  person Maarten Bodewes    schedule 22.11.2011


Ответы (2)


Он печатается, когда я запускаю его. Вы можете добавить System.out.flush(); в конец метода run(), это гарантирует, что вывод будет напечатан немедленно.

person Maarten Bodewes    schedule 22.11.2011
comment
В JRE обычно да, но я только что просмотрел описание System.out и println, и он явно не требует автоматической очистки. И затем может случиться так, что принимающая сторона выполняет буферизацию, а затем преждевременно закрывается. Поэтому нам нужно знать систему, в которой работает спрашивающий. - person Maarten Bodewes; 22.11.2011
comment
Я пробовал это как на Cygwin, так и на Windows из командной строки. Он печатает его, когда вы запускаете потоки? Не знаю, как разместить код, не создавая новую тему, пожалуйста, посоветуйте. - person user998388; 23.11.2011

как говорили другие, это должно просто работать. Какую ОС вы используете? Возможно, CTRL+C полностью убивает процесс, а не просит его завершить работу (например, SIGKILL против SIGINT). Можете ли вы проверить, какой сигнал вы отправляете процессу Java?

Наконец, в крайнем случае вы можете попробовать следующий фрагмент Java:

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

Я подозреваю, что это не будет иметь никакого значения, хотя!

person Muel    schedule 22.11.2011
comment
Любые идеи? Я использую JDK и Netbeans в Windows. - person user998388; 11.12.2011