Новости из мира ПК
5 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд

Java thread interrupt

How interrupt/stop a thread in Java?

I’m trying to stop a thread but I can’t do that :

So, even when i call the method ‘stop’ the thread don’t stop. It keeps alive.

How can I interrupt/stop this thread ?

UPDATE (@little approach)

The Middleware class :

But when I try to stop the thread, it doesn’t.

What could be wrong in the code above ?

8 Answers 8

There’s really no reason you need to use a volatile flag. Instead, just query the thread for its state with isInterrupted() . Also, why are you wrapping your Scan thread object in another thread object? That seems completely unnecessary to me.

Here’ what you should be doing

Here’s an example. Also, I wouldn’t recommend extending Thread .

Simply return; from your while and the thread will die, no need to call stop() or interrupt(). If you want to do it externally then use this pattern and call requestStop() .

The usual way to stop a thread is to have a volatile flag and then check that in the run method. i.e.

You can then call scan.stop() .

«Many uses of stop() should be replaced by code that simply modifies some variable to indicate that the target thread should stop running.»— java.lang.Thread

if you want to interrupt a running thread, then you need to have access to the thread object.

this will interrupt the running thread.

Completely agree with Jim.. Just to add If your thread is blocked inside the try block for instance reading on a datastream etc then interrupt the thread as well or close the stream. In both cases the thread should be wakened up again and it will then be able to see the change in the value of «stop» boolean and die naturally by falling out of the run method. At least this is what I did to kill my threads in the shutdown thread for my server.

Rather than using Thread.stop() or Thread.interrupt() you can go for the external locks. Basically, when you try to utilize an intrinsic lock most of the time any interrupt you perform on the thread is uncontrollable.

A re-entrant lock provides you the methods as mentioned below

Check the below example

This makes your code elegant and handle the interrupt in a better way.

Not the answer you’re looking for? Browse other questions tagged java multithreading or ask your own question.



Hot Network Questions

Subscribe to RSS

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

site design / logo © 2020 Stack Exchange Inc; user contributions licensed under cc by-sa 4.0 with attribution required. rev 2020.4.3.36511

Understanding Thread Interruption in Java

How to get a task running on a separate thread to finish early, or make that task responsive to such a finish request.

Join the DZone community and get the full member experience.

You may come across use cases where you would need to perform some long running tasks on separate threads. You may have to request these tasks to finish doing their work, maybe even before the tasks are completely done, so that the threads they would be running on can be stopped. A few situations in which you may have to finish tasks early and stop threads are:

  • While servicing a web request you may distribute the processing to multiple threads and some or all of the tasks fail to finish the processing within specified request processing time, or
  • While shutting down an application that may use more than one thread to do some work, which may not have completed.

In this article I will try to answer the following questions:

  • How to request a task, running on a separate thread, to finish early?
  • How to make a task responsive to such a finish request?

Let’s try to answer the two questions by implementing an use case.

Example Use Case

The following are the requirements of the use case:

  1. Make a task that prints 0 through 9 on console.
  2. After printing a number the task should wait 1 sec before printing the next number.
  3. The task runs on a separate thread, other than main application thread.
  4. After starting the task the main application should wait for 3 sec and then shutdown.
  5. On shutdown the application should request the running task to finish.
  6. Before shutting down completely the application should, at the max, wait for 1 sec for the task to finish.
  7. The task should respond to the finish request by stopping immediately.

As per the requirements mentioned in the use case the task will take minimum 9 seconds to complete. Therefore after 3 seconds the main application will have to request the task to finish and if implemented correctly the task will not be able to print all the ten numbers from 0 through 9.

In this article, I will be focusing on the implementations of requirement 5 and requirement 7.

An Implementation of the Use Case Using Thread

The inline comment against a line of code mentions the use case requirement that has been met by the line.

Читать еще:  Java nio channels

Understanding the Implementation of Requirement 5

In the implementation of requirement 5, the main thread calls the taskThread ’s interrupt() method. In Java, one thread cannot stop the other thread. A thread can only request the other thread to stop. The request is made in the form of an interruption. Calling the interrupt() method on an instance of a Thread sets the interrupt status state as true on the instance.

Use interruption to request a task, running on a separate thread, to finish.

Understanding the Implementation of Requirement 7

In the implementation of requirement 7, InterruptedException is being handled by breaking out of the loop and thus finishing the task early.

Question arises that why did Thread.sleep() throw an InterruptedException? As soon as the taskThread was interrupted by the main thread, the Thread.sleep(1_000) responded to the interruption by throwing the exception. In fact almost all blocking methods respond to interruption by throwing InterruptedException.The decision of what to do in the case of interruption is left to the implementing code, which in this example is breaking out of the for loop as per the requirement in the use case.

Note: Calls to sleep() and join() methods in main() method are blocking and may also throw InterruptedException upon interruption. Handling of the exception here has been omitted for brevity.

Handle interruption request, which in most cases is done by handling InterruptedException, in the task to make it responsive to a finish request.

An Implementation of the Use Case Using the Executor

The same use case can be implemented using Executor framework provided by Java and can be found under the java.util.concurrent package. Usage of the Executor framework is preferred over Threads as it provides separation of task execution from the thread management. In the implementation below the task is submitted to ExecutorService , a sub-interface of Executor, using the submit() method. The service runs the task on the thread it holds. The service’s shutdownNow() method interrupts the currently running task and awaitTermination() method waits for the service to shutdown.

When using the Executor framework, you can interrupt a specific task without shutting down the ExecutorService . On submitting a task to the service an instance of Future is returned by the service. You may call the cancel() method on that instance to interrupt the task. In situations when you service a web request by running parallel tasks, this method of cancelling tasks and not shutting down the service helps in re-using the service across multiple requests. In such situations you may want to shutdown the service only on shutdown of your web application. Calling the cancel() with true causes the task to be interrupted.

The Executor framework is a complete asynchronous task execution framework. If you have not explored it yet, I request to you to read about it. It will be a great addition to your development toolbox.

InterruptedException and Interruption Status

Before I finish, I wanted to emphasize on an important detail about what happens to a thread’s interruption status when a blocking code responds to interruption by throwing InterruptedException . I had left out the detail till now to avoid confusion.

Before a blocking code throws an InterruptedException, it marks the interruption status as false. Thus, when handling of the InterruptedException is done, you should also preserve the interruption status by calling Thread.currentThread().interrupt() .

Let’s see how this information applies to the example below. In the task that is submitted to the ExecutorService, the printNumbers() method is called twice. When the task is interrupted by a call to shutdownNow() , the first call to the method finishes early and then the execution reaches the second call. The interruption is called by the main thread only once. The interruption is communicated to the second execution of the printNumber() method by the call to Thread.currentThread().interrupt() during the first execution. Hence the second execution also finishes early just after printing the first number. Not preserving the interruption status would have caused the second execution of the method to run fully for 9 seconds.

Читать еще:  Javascript проверка на nan


The answers to the two questions that I had set out to answer are:

Java thread interrupt

Примеры потоков ранее представляли поток как последовательный набор операций. После выполнения последней операции завершался и поток. Однако нередко имеет место и другая организация потока в виде бесконечного цикла. Например, поток сервера в бесконечном цикле прослушивает определенный порт на предмет получения данных. И в этом случае мы также можем предусмотреть механизм завершения потока.

Завершение потока

Распространенный способ завершения потока представляет опрос логической переменной. И если она равна, например, false, то поток завершает бесконечный цикл и заканчивает свое выполнение.

Определим следующий класс потока:

Переменная isActive указывает на активность потока. С помощью метода disable() мы можем сбросить состояние этой переменной.

Теперь используем этот класс:

Итак, вначале запускается дочерний поток: new Thread(myThread,»MyThread»).start() . Затем на 1100 миллисекунд останавливаем Main thread и потом вызываем метод myThread.disable() , который переключает в потоке флаг isActive. И дочерний поток завершается.

Метод interrupt

Еще один способ вызова завершения или прерывания потока представляет метод interrupt() . Вызов этого метода устанавливает у потока статус, что он прерван. Сам метод возвращает true, если поток может быть прерван, в ином случае возвращается false.

При этом сам вызов этого метода НЕ завершает поток, он только устанавливает статус: в частности, метод isInterrupted() класса Thread будет возвращать значение true. Мы можем проверить значение возвращаемое данным методом и прозвести некоторые действия. Например:

В классе, который унаследован от Thread, мы можем получить статус текущего потока с помощью метода isInterrupted() . И пока этот метод возвращает false, мы можем выполнять цикл. А после того, как будет вызван метод interrupt, isInterrupted() возвратит true, и соответственно произойдет выход из цикла.

Возможный консольный вывод:

Если основная функциональность заключена в классе, который реализует интерфейс Runnable, то там можно проверять статус потока с помощью метода Thread.currentThread().isInterrupted() :

Однако при получении статуса потока с помощью метода isInterrupted() следует учитывать, что если мы обрабатываем в цикле исключение InterruptedException в блоке catch, то при перехвате исключения статус потока автоматически сбрасывается, и после этого isInterrupted будет возвращать false.

Например, добавим в цикл потока задержку с помощью метода sleep:

Когда поток вызовет метод interrupt, метод sleep сгенерирует исключение InterruptedException, и управление перейдет к блоку catch. Но если мы проверим статус потока, то увидим, что метод isInterrupted возвращает false. Как вариант, в этом случае мы можем повторно прервать текущий поток, опять же вызвав метод interrupt(). Тогда при новой итерации цикла while метода isInterrupted возвратит true, и поизойдет выход из цикла.

Либо мы можем сразу же в блоке catch выйти из цикла с помощью break:

Если бесконечный цикл помещен в конструкцию try. catch, то достаточно обработать InterruptedException:

Собеседование по Java — многопоточность (вопросы и ответы)

Вопросы и ответы для собеседования Java по теме — многопоточность.

К списку вопросов по всем темам


1. Дайте определение понятию “процесс”.
2. Дайте определение понятию “поток”.
3. Дайте определение понятию “синхронизация потоков”.
4. Как взаимодействуют программы, процессы и потоки?
5. В каких случаях целесообразно создавать несколько потоков?
6. Что может произойти если два потока будут выполнять один и тот же код в программе?
7. Что вы знаете о главном потоке программы?
8. Какие есть способы создания и запуска потоков?
9. Какой метод запускает поток на выполнение?
10. Какой метод описывает действие потока во время выполнения?
11. Когда поток завершает свое выполнение?
12. Как синхронизировать метод?
13. Как принудительно остановить поток?
14. Дайте определение понятию “поток-демон”.
15. Как создать поток-демон?
16. Как получить текущий поток?
17. Дайте определение понятию “монитор”.
18. Как приостановить выполнение потока?
19. В каких состояниях может пребывать поток?
20. Что является монитором при вызове нестатического и статического метода?
21. Что является монитором при выполнении участка кода метода?
22. Какие методы позволяют синхронизировать выполнение потоков?
23. Какой метод переводит поток в режим ожидания?
24. Какова функциональность методов notify и notifyAll?
25. Что позволяет сделать метод join?
26. Каковы условия вызова метода wait/notify?
27. Дайте определение понятию “взаимная блокировка”.
28. Чем отличаются методы interrupt, interrupted, isInterrupted?
29. В каком случае будет выброшено исключение InterruptedException, какие методы могут его выбросить?
30. Модификаторы volatile и метод yield().
31. Пакет java.util.concurrent
32. Есть некоторый метод, который исполняет операцию i++. Переменная i типа int. Предполагается, что код будет исполнятся в многопоточной среде. Следует ли синхронизировать блок?
33. Что используется в качестве mutex, если метод объявлен static synchronized? Можно ли создавать новые экземпляры класса, пока выполняется static synchronized метод?
34. Предположим в методе run возник RuntimeException, который не был пойман. Что случится с потоком? Есть ли способ узнать о том, что Exception произошел (не заключая все тело run в блок try-catch)? Есть ли способ восстановить работу потока после того как это произошло?
35. Какие стандартные инструменты Java вы бы использовали для реализации пула потоков?
36.Что такое ThreadGroup и зачем он нужен?
37.Что такое ThreadPool и зачем он нужен?
38.Что такое ThreadPoolExecutor и зачем он нужен?
39.Что такое «атомарные типы» в Java?
40.Зачем нужен класс ThreadLocal?
41.Что такое Executor?
42.Что такое ExecutorService?
43.Зачем нужен ScheduledExecutorService?

Читать еще:  Структура проекта java


1. Дайте определение понятию “процесс”.

Процесс — это совокупность кода и данных, разделяющих общее виртуальное адресное пространство. Процессы изолированы друг от друга, поэтому прямой доступ к памяти чужого процесса невозможен (взаимодействие между процессами осуществляется с помощью специальных средств). Для каждого процесса ОС создает так называемое «виртуальное адресное пространство», к которому процесс имеет прямой доступ. Это пространство принадлежит процессу, содержит только его данные и находится в полном его распоряжении. Операционная система же отвечает за то, как виртуальное пространство процесса проецируется на физическую память.

Многопоточность в Java:

2. Дайте определение понятию “поток”.

Один поток («нить» или «трэд») – это одна единица исполнения кода. Каждый поток последовательно выполняет инструкции процесса, которому он принадлежит, параллельно с другими потоками этого процесса.

Thinking in Java.Параллельное выполнение.

3. Дайте определение понятию “синхронизация потоков”.

Синхронизация относится к многопоточности. Синхронизированный блок кода может быть выполнен только одним потоком одновременно.

Java поддерживает несколько потоков для выполнения. Это может привести к тому, что два или более потока получат доступ к одному и тому же полю или объекту. Синхронизация — это процесс, который позволяет выполнять все параллельные потоки в программе синхронно. Синхронизация позволяет избежать ошибок согласованности памяти, вызванных непоследовательным доступом к общей памяти.
Когда метод объявлен как синхронизированный — нить держит монитор для объекта, метод которого исполняется. Если другой поток выполняет синхронизированный метод, ваш поток заблокируется до тех пор, пока другой поток не отпустит монитор.
Синхронизация достигается в Java использованием зарезервированного слова synchronized. Вы можете использовать его в своих классах определяя синхронизированные методы или блоки. Вы не сможете использовать synchronized в переменных или атрибутах в определении класса.

Синхронизация потоков, блокировка объекта и блокировка класса

4. Как взаимодействуют программы, процессы и потоки?

Чаще всего одна программа состоит из одного процесса, но бывают и исключения (например, браузер Chrome создает отдельный процесс для каждой вкладки, что дает ему некоторые преимущества, вроде независимости вкладок друг от друга). В каждом процессе может быть создано множество потоков. Процессы разделены между собой (>программы), потоки в одном процессе могут взаимодействовать друг с другом (методы wait, notify, join и т.д.).

5. В каких случаях целесообразно создавать несколько потоков?

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

6. Что может произойти если два потока будут выполнять один и тот же код в программе?

Если используются не синхронизированные данные, то может произойти ситуация, когда код работает уже с устаревшими данными. Например, в первом потоке идет изменение каких-либо полей, а в это время второй поток читает эти поля.

7. Что вы знаете о главном потоке программы?

Маленькие программы на Java обычно состоят из одной нити, называемой «главной нитью» (main thread). Но программы побольше часто запускают дополнительные нити, их еще называют «дочерними нитями». Главная нить выполняет метод main и завершается. Аналогом такого метода main, для дочерних нитей служит метод run интерфейса Runnable. Много потоков — много методов main (run()).

8. Какие есть способы создания и запуска потоков?

Существует несколько способов создания и запуска потоков.

С помощью класса, реализующего Runnable

  • Создать объект класса Thread .
  • Создать объект класса, реализующего интерфейс Runnable
  • Вызвать у созданного объекта Thread метод start() (после этого запустится метод run() у переданного объекта, реализующего Runnable )

С помощью класса, расширяющего Thread

  • Создать объект класса ClassName extends Thread .
  • Переопределить run() в этом классе (смотрите пример ниже, где передается имя потока ‘Second’)

С помощью класса, реализующего java.util.concurrent.Callable

  • Создать объект класса, реализующего интерфейс Callable
  • Создать объект ExecutorService с указанием пула потоков.
  • Создать объект Future. Запуск происходит через метод submit() ; Сигнатура: Future submit(Callable task)
Ссылка на основную публикацию