Напишите поток, который можно приостановить, продолжить/возобновить его выполнение и остановить.
Это вопрос на знание нескольких фактов:
Как в Java создать поток
Знание того факта, что Thread.stop(), Thread.suspend() и Thread.resume() не безопасны и deprecated. Их нельзя использовать.
Знание wait-notify механизма в Java
Знание volatile и/или synchronized в Java
Как работает interrupt()
В Java есть встроенные методы Thread.stop(), Thread.suspend() и Thread.resume() методы у класса Thread. И новичку в многопоточности может показаться, что нужно, просто, их и использовать для этих целей. Но если вы так ответите, это будет красным флагом для вас. Интервьюер поймет, что вы не знаете этой темы совсем.
Эти методы в Java deprecated, т.к. они не безопасны. Почему это так можно почитать в официальной документации тут: https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Кратко:
Thread.stop() — бросает Error: ThreadDeath, это приводит к тому, что поток отпускает все мониторы(локи), которые держал. Если какие-то объекты были защищены этими мониторами, то они могут оказаться в промежуточном/неконсистентном состоянии. При этом другие потоки, не будут знать, что произошла остановка потока при помощи Thread.stop() и некоторые объекты могут быть в промежуточном состоянии. Это приведет к неправильной работе приложения.
Thread.suspend() — заставляет поток перейти в режим ожидания, но если поток держал какие-то мониторы(локи), то он продолжит их держать. Это может привести к dead-lock. Например, если второй поток, который должен разбудить первый тоже должен вначале получить лок на тот же объект. Они будут вечно друг друга ждать.
Как же правильно остановить поток?
Использовать метод interrupt() + в методе run потока проверять флаг isInterruped() и реагировать на InterruptedException, который могут бросить блокирующие операции.
Как можно приостановить и возобновить выполнение потока?
Например, при помощи wait-notify механизма. Смотри мои статьи про методы Object и задачу на wait-notify: Ping-Pong.
В run добавим:
synchronized (this) {
while (isSuspended) {
wait();
}
}
И чтобы приостановить:
isSuspended = true;
Важный момент: isSuspended должна меняться или в synchronized блоке или быть объявленной как volatile для обеспечения visibility. Смотрите более подробно про volatile: https://www.baeldung.com/java-volatile
volatile boolean isSuspended
И чтобы возобновить работу потока:
public synchronized void customResume() {
this.isSuspended = false;
notifyAll();
}
Итого, все вместе:
public class Main {
public static void main(String[] args) throws InterruptedException {
ResumableThread t = new ResumableThread();
t.start();
Thread.sleep(10000);
t.customSuspend();
Thread.sleep(10000);
t.customResume();
Thread.sleep(10000);
t.customTerminate();
}
}
class ResumableThread extends Thread {
private volatile boolean isSuspended;
public synchronized void customResume() {
this.isSuspended = false;
notifyAll();
}
public void customSuspend() {
this.isSuspended = true;
}
public void customTerminate() {
interrupt();
}
public void run() {
try {
while (!isInterrupted()) {
doWork();
synchronized (this) {
while (isSuspended) {
System.out.println("Going to sleep");
wait();
}
}
}
System.out.println("Interrupted");
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
}
private void doWork() throws InterruptedException {
// Что-то очень важное выполняем
System.out.println("Doing some work");
Thread.sleep(1000);
}
}
Top comments (0)