Подтвердить что ты не робот

Thread.stop() - устаревший

Почему Thread.stop() устарел на Java? На их веб-сайте я вижу следующее:

Почему Thread.stop устарел?

Потому что это по своей сути небезопасно. Остановка потока заставляет его разблокировать все мониторы, которые он заблокировал. (Мониторы разблокируются, так как исключение ThreadDeath распространяется на стек.) Если какой-либо из объектов, ранее защищенных этими мониторами, находился в несогласованном состоянии, другие потоки теперь могут просматривать эти объекты в несогласованном состоянии. Такие объекты, как говорят, повреждены. Когда потоки работают на поврежденных объектах, может возникнуть произвольное поведение. Такое поведение может быть тонким и трудным для обнаружения, или оно может быть выражено. В отличие от других исключенных исключений, ThreadDeath убивает потоки молча; таким образом, пользователь не предупреждает, что его программа может быть повреждена. Коррупция может проявиться в любое время после фактического ущерба, даже в часы или дни в будущем.

Я не понимаю, что они подразумевают под "мониторами". Независимо от того, мой вопрос: если Thread.stop() не следует вызывать, то как должен быть остановлен поток Java?

4b9b3361

Ответ 1

Вы спросили:

Мой вопрос в том, что если нет способа остановить поток в Java, то как остановить поток?

Ответ. В Java нет чистого, быстрого или надежного способа остановить поток.

Прекращение резьбы не так прямо. Бегущая нить, часто называемая многими писателями в виде легкого процесса, имеет свой собственный стек и является хозяином своей собственной судьбы (ну демоны есть). Он может иметь файлы и сокеты. Он может содержать блокировки. Резкое прекращение не всегда легко: непредсказуемые последствия могут возникнуть, если поток находится в середине письма в файл и убит, прежде чем он сможет закончить запись. Или как насчет блокировок монитора, удерживаемых нитью при выстреле в голову?

Вместо этого Threads полагаются на механизм сотрудничества, называемый Прерывание. Это означает, что потоки могут сигнализировать только о том, чтобы остановить другие потоки, а не заставить их остановиться.

Чтобы остановить потоки в Java, мы полагаемся на кооперативный механизм, называемый прерыванием. Концепция очень проста. Чтобы остановить поток, все, что мы можем сделать, это передать ему сигнал, а также прервать его, запросив, чтобы поток остановился при следующей доступной возможности. Это все. Неизвестно, что может сделать поток приемника с сигналом: он даже не может проверить сигнал; или даже хуже игнорировать его.

Источник: http://10kloc.wordpress.com/2013/03/03/java-multithreading-steeplechase-stopping-threads/

Ответ 2

Правильный способ - использовать соединение. Вместо того, чтобы преждевременно прекратить выполнение потока, соединение будет ждать завершения потока, прежде чем перейти к следующему оператору.

Thread exampleThread = new Thread(){
    public void run(){
        try {

            Thread.sleep(2000);

        } catch (InterruptedException ex) {
            //handle the exception
        }
    }
};

exampleThread.start();
exampleThread.join();

Здесь exampleThread.join() будет ждать выполнения примераThread, прежде чем перейти к следующему утверждению. Тем не менее, ответственность за то, чтобы поток выполнял выполнение, находится на программиста. По сути, нет способа остановить поток, но если вы правильно его разработали, вам не нужно останавливать поток.

Ответ 3

Когда ваш поток обрабатывает прерывания правильно, должно быть возможно немедленно завершить его с использованием интерфейса ExecutorService. Согласно документации Oracle, метод ExecutorService.shutdownNow(), пытается остановить все активные выполнение задач, не дожидаясь их завершения. Тем не менее, нет никаких гарантий, кроме попыток прекратить их попытки. Вот пример кода:

class MyThread implements Runnable{
    @Override
    public void run() {
        for (int i = 1; i < 10000000; i++)
            try {
            System.out.println(i + " ThreadID: " + Thread.currentThread().getId());
            if (Thread.interrupted()) 
                    throw new InterruptedException();
            } catch (InterruptedException e) {
                return;
        }   
    }
}

ExecutorService executor = Executors.newFixedThreadPool(3);
            executor.submit(new MyThread());
            executor.submit(new MyThread());
            executor.submit(new MyThread());
            executor.shutdownNow();

Без прерывания каждый поток должен печатать сообщение на консоль 10000000 раз. executor.shutdownNow() мгновенно останавливает все три потока.

Ответ 4

Из https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html:

Большинство применений остановки следует заменить кодом, который просто изменяет некоторую переменную, чтобы указать, что целевой поток должен прекратить работу. Целевой поток должен регулярно проверять эту переменную и возвращаться из метода запуска упорядоченным способом, если переменная указывает, что она должна прекратиться. Чтобы обеспечить быстрое сообщение запроса на остановку, переменная должна быть изменчивой (или доступ к переменной должен быть синхронизирован).