JAVAスレッド停止の方法

11775 ワード

スレッドを終了させるには3つの方法があります.     1.終了フラグを使用して、runメソッドが完了するとスレッドが正常に終了します.     2.stopメソッドを使用してスレッドを強制的に終了します(stopはsuspend、resumeと同様に予期せぬ結果が発生する可能性があるため、このメソッドは推奨されません).廃棄3.interruptメソッドを使用してスレッドを中断します. 
 
 
Javaのスレッドをどのように停止するかは、私たちがマルチスレッドプログラムを開発するのに悩んでいる問題です.この質問は最終的にJava 5のjava.util.concurrentで回答を得た:使用interrupt()runメソッドでスレッドを停止させる.
概要
Javaのマルチスレッドプログラミングでは、java.lang.Threadタイプにいくつかの列が含まれている方法start()stop()stop(Throwable)andsuspend()destroy()andresume().これらの方法により,スレッドを容易に操作できるが,これらの方法のうち,start()方法のみが保持されている.
Sun社の『Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?』では、これらの方法を捨てる理由を詳しく解説しています.では、スレッドをどのように停止すればいいのでしょうか.
推奨される使用方法
Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?』では、スレッドを停止するには、以下の方法を推奨します.
    private volatile Thread blinker;     public void stop() {         blinker = null;     }     public void run() {         Thread thisThread = Thread.currentThread();         while (blinker == thisThread) {             try {                 thisThread.sleep(interval);             } catch (InterruptedException e){             }             repaint();         }     }
volatileキーワードを使用する理由については、http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#36930を参照してください.
スレッドが非実行(Run)状態にある場合
スレッドが次の状態にある場合は、非実行状態になります.
  • sleepメソッドが呼び出されたとき.
  • waitメソッドが呼び出されると.
  • I/Oブロックされている場合、ファイルやネットワークなどである可能性があります.

  • スレッドが上記の状態にある場合、前述の方法では使用できません.このとき、私たちはinterrupt()ブロックを破るために使用することができます.
    public void stop() {
    Thread tmpBlinker = blinker;
    blinker = null;
    if (tmpBlinker != null) {
    tmpBlinker.interrupt();
    }
    }

    interrupt()呼び出されるとInterruptedException投げ出されるのでrunメソッドでこの異常をキャプチャし、スレッドを安全に終了させることができます.
    try {
    ....
    wait();
    } catch (InterruptedException iex) {
    throw new RuntimeException("Interrupted",iex);
    }

    ブロックI/O
    スレッドがI/Oでブロックされている場合、呼び出しinterrupt()の場合は、実際に稼働しているプラットフォームに依存します.SolarisとLinuxプラットフォームではInterruptedIOExceptionの例外が投げ出されますが、Windowsではこのような例外はありません.だから、私たちはこのような問題をプラットフォームの実現に頼ることはできません.次のようになります.
    package com.cnblogs.gpcuster

    import java.net.*;
    import java.io.*;

    public abstract class InterruptibleReader extends Thread {

    private Object lock = new Object( );
    private InputStream is;
    private boolean done;
    private int buflen;
    protected void processData(byte[] b, int n) { }

    class ReaderClass extends Thread {

    public void run( ) {
    byte[] b = new byte[buflen];

    while (!done) {
    try {
    int n = is.read(b, 0, buflen);
    processData(b, n);
    } catch (IOException ioe) {
    done = true;
    }
    }

    synchronized(lock) {
    lock.notify( );
    }
    }
    }

    public InterruptibleReader(InputStream is) {
    this(is, 512);
    }

    public InterruptibleReader(InputStream is, int len) {
    this.is = is;
    buflen = len;
    }

    public void run( ) {
    ReaderClass rc = new ReaderClass( );

    synchronized(lock) {
    rc.start( );
    while (!done) {
    try {
    lock.wait( );
    } catch (InterruptedException ie) {
    done = true;
    rc.interrupt( );
    try {
    is.close( );
    } catch (IOException ioe) {}
    }
    }
    }
    }
    }

     
    また、InterruptibleChannelインターフェースも使用できます.実現したInterruptibleChannelインターフェースのクラスはブロック時に投げ出すことができるClosedByInterruptException.次のようになります.
    package com.cnblogs.gpcuster

    import java.io.BufferedReader;
    import java.io.FileDescriptor;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.nio.channels.Channels;

    public class InterruptInput {
    static BufferedReader in = new BufferedReader(
    new InputStreamReader(
    Channels.newInputStream(
    (new FileInputStream(FileDescriptor.in)).getChannel())));

    public static void main(String args[]) {
    try {
    System.out.println("Enter lines of input (user ctrl+Z Enter to terminate):");
    System.out.println("(Input thread will be interrupted in 10 sec.)");
    // interrupt input in 10 sec (new TimeOut()).start();
    String line = null;
    while ((line = in.readLine()) != null) {
    System.out.println("Read line:'"+line+"'");
    }
    } catch (Exception ex) {
    System.out.println(ex.toString()); // printStackTrace(); } } public static class TimeOut extends Thread {
    int sleepTime = 10000;
    Thread threadToInterrupt = null;
    public TimeOut() {
    // interrupt thread that creates this TimeOut. threadToInterrupt = Thread.currentThread(); setDaemon(true);
    }

    public void run() {
    try {
    sleep(10000); // wait 10 sec } catch(InterruptedException ex) {/*ignore*/}
    threadToInterrupt.interrupt();
    }
    }
    }

    ここでは、スレッドがファイルを書いている状態のときに呼び出されるinterrupt()スレッドは中断されないことに注意してください.
    参考資料
    How to Stop a Thread or a Task
    Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?