Выполнение потока после его прерывания

#multithreading #thread-sleep

#многопоточность #поток-сон

Вопрос:

Поток выполняет задачу по печати чисел от 0 до n и переходит в спящий режим в течение 4000 мс после каждого оператора печати. Где-то в середине поток прерывается. Теперь, когда тот же поток начнет свое выполнение, с чего он начнется, начнет ли он снова печатать числа от 0 до n или он будет печатать числа с того места, где он был прерван. В обоих случаях каковы причины и как это обрабатывается?

 
public class Main {

    public static void main(String[] args) throws InterruptedException {
   
        SleepTest sleepTest = new SleepTest();
        Thread thread = new Thread(sleepTest);
        thread.start();
        thread.interrupt();

    }
}
public class SleepTest implements Runnable{
static int sleep = 10;
    public void run(){
        for (int i =0; i<10; i  ){
           System.out.println(i);

            try {
                Thread.currentThread().interrupt();
              Thread.sleep(4000);

            } catch (InterruptedException exception) {

                exception.printStackTrace();

            }
            System.out.println(Thread.interrupted());
        }
    }

  

Ответ №1:

Вызов a interrupt() для объекта потока может только предложить потоку остановиться. Это не гарантирует, что поток остановится.
Это полностью зависит от реализации run() метода потока.

В вашем случае run() вы перехватываете InterruptedException и печатаете трассировку исключения, но не останавливаете поток. Вот почему поток никогда не остановится InterruptedException и не продолжит выполнение.
Может показаться, что поток останавливается (при просмотре трассировки исключения), когда отображается вывод на консоль.

Ссылка прерывание прерывание прерывается в Java

Ответ №2:

Все Thread.currentThread().interrupt() , что нужно, это обновить значение поля interrupted до true .

Давайте посмотрим, как работает программа и как interrupted полю присваиваются значения:

 
    public class Main {
    
        public static void main(String[] args) throws InterruptedException {
       
            SleepTest sleepTest = new SleepTest();
            Thread thread = new Thread(sleepTest, "Sub Thread"); // Give a name to this thread
            thread.start(); // main thread spawns the "Sub Thread". Value of "interrupted" - false
            thread.interrupt(); // called by main thread. Value of "interrupted" - true
    
        }
    }
    public class SleepTest implements Runnable{
        static int sleep = 10;
        public void run(){
            System.out.println(Thread.currentThread().getName() " " Thread.interrupted()); // prints "Sub Thread true"
            for (int i =0; i<10; i  ){
               System.out.println(i);
    
                try {
                  Thread.currentThread().interrupt(); // no matter what value is for interrupted, it is assigned the value "true"
                  Thread.sleep(4000); // Can't call sleep with a "true" interrupted status. Exception is thrown. Note that, when the exception is thrown, the value of interrupted is "reset", i.e., set to false
    
                } catch (InterruptedException exception) {
    
                    exception.printStackTrace(); // whatever
    
                }
                System.out.println(Thread.interrupted()); // returns the value of interrupted and resets it to false
            }
        }

  

Чтобы ответить

с чего он начнется, начнет ли он снова печатать числа от 0 до n или будет печатать числа с того места, где он был прерван.

Вызов прерывания не приведет к его началу заново, потому что все, что он делает при этом вызове, — это устанавливает значение interrupted false (и не изменяет ничего другого).