第61回 割り込み
今回のテーマは前回に引き続き「割り込み」です。
前回はスレッドに対して割り込みを行うのに、そのスレッドのinterruptメソッドを実行することについて書きました。
今回はExecutorを使用して起動したスレッドに対して割り込みを行うことを考えてみます。
Executorを使用した場合、Threadインスタンスは表には出てきません。
タスクを取り消すには、非同期処理の結果を表すFutureのcancel メソッドを実行します。
タスクを実行しているスレッドに割り込むかどうかは、引数で指定します。
次のサンプルコードは前回同様、キャンセル可能なタスクを実行するSwingアプリケーションです。
バックグラウンドスレッドを起動するのにExecutorServiceを使用しています。(J2SE5.0以上対応)
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.UIManager; public class MainWindow extends JFrame implements ActionListener, Runnable { private static final long serialVersionUID = 1L; public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { try { UIManager.setLookAndFeel(UIManager .getSystemLookAndFeelClassName()); } catch (Exception e) {} new MainWindow(); } }); } private JPanel jPanel = new JPanel(); private JButton runButton = new JButton("処理開始"); private JButton cancelButton = new JButton("キャンセル"); private ExecutorService executorService = Executors.newSingleThreadExecutor(); private Future future; public MainWindow() { runButton.addActionListener(this); cancelButton.addActionListener(this); cancelButton.setEnabled(false); jPanel.add(runButton); jPanel.add(cancelButton); setContentPane(jPanel); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(300, 75); setLocationRelativeTo(null); setVisible(true); } public void actionPerformed(ActionEvent actionEvent) { if (runButton.equals(actionEvent.getSource())) { runButton.setEnabled(false); cancelButton.setEnabled(true); future = executorService.submit(this); } if (cancelButton.equals(actionEvent.getSource())) { future.cancel(true); } } public void run() { for (int i = 0; i < 10000000; i++) { if (Thread.interrupted()) { break; } } SwingUtilities.invokeLater(new Runnable() { public void run() { runButton.setEnabled(true); cancelButton.setEnabled(false); } }); } }
ちなみにsleepメソッド、waitメソッドなどを実行し、待機中のスレッドに対して割り込みを行った場合、そのスレッド側でInterruptedExceptionがスローされます。