Итак, чтобы поддерживать один экземпляр Runnable
, вы можете запланировать его работу на него, когда это необходимо. Что-то вроде планирования одного и того же Runnable
в одном потоке ExecutorService
...
Вы должны поместить весь блок try-catch вне while
l oop, поскольку прерывание означает внезапное завершение времени выполнения Thread
, поэтому Thread
должен предпринять свои последние действия для освобождения / распоряжения своими ресурсами перед завершением.
Затем вы также можете добавить переменную boolean
указывает, должен ли Thread
завершаться или продолжать работать. Эта переменная соответствует условию while
l oop. Разница здесь в том, что мы не прерываем Thread
, но вместо этого мы ждем, пока критическая часть работы не будет завершена, и затем нормально завершаем работу while
l oop (также распределяя ресурсы после этого).
По существу, пользовательский опыт может заключаться в том, что подход прерывания убивает работу в середине, тогда как обычное завершение занимает немного больше времени, но изящно.
Помещение вместе с этими заметками вы можете получить что-то вроде следующего кода:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main2 {
public static class DisposableRunnable implements Runnable {
private boolean on = true;
@Override
public void run() {
try {
while (isOn())
doSomeWork();
System.out.println(Thread.currentThread().getName() + " is stopped gracefully.");
}
catch (final InterruptedException ix) {
System.out.println(Thread.currentThread().getName() + " is stopped abruptly: " + ix);
}
finally {
dispose();
}
}
//Do whatever work the thread has to do, in this method:
private void doSomeWork() throws InterruptedException {
for (int i = 0; i < 5; ++i) {
System.out.println("Working " + i + "...");
Thread.sleep(500); //Delay a bit, to simulate a lengthy work in progress.
}
}
private void dispose() {
//Relinquish resources here...
}
public synchronized boolean isOn() {
return on;
}
public synchronized void stop() {
on = false;
}
}
public static class MainFrame extends JFrame {
private final Thread mt;
private final DisposableRunnable run;
public MainFrame() {
run = new DisposableRunnable();
mt = new Thread(run);
final JPanel jp = new JPanel();
final JButton jb1 = new JButton("Click to stop.");
final JButton jb2 = new JButton("Click to interrupt.");
jb1.addActionListener(e -> {
run.stop();
jb1.setText("Stopped.");
jb1.setEnabled(false);
jb2.setEnabled(false);
});
jb2.addActionListener(e -> {;
mt.interrupt();
jb2.setText("Interrupted");
jb1.setEnabled(false);
jb2.setEnabled(false);
});
jp.add(jb1);
jp.add(jb2);
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
super.getContentPane().add(jp);
super.pack();
super.setLocationRelativeTo(null);
}
public void startOnce() {
mt.start();
setVisible(true);
}
}
public static void main(final String[] args) {
new MainFrame().startOnce();
}
}
Разница в том, что мы делаем только один экземпляр Runnable
(а также один экземпляр Thread
, который запускает Runnable
).
Обратите также внимание, что реализация метода doSomeWork
может быть настолько простой, что он даже не выдает InterruptedException
, что означает, что единственным формальным способом остановки Thread
будет установите флаг boolean
, о котором мы говорили (в данном случае переменная on
), на false
, а ожидание последнего фрагмента работы (ie метод doSomeWork
) на значение Fini * 104. 4 *.