JAvaスレッドキャンセル方式

10121 ワード

JAVAタスクキャンセル方式には一般的に2種類の第1種類のキャンセルフラグが設定されており、タスクは定期的にこのフラグを表示している.この方式にはタスクキャンセルが存在し、タスクの即時キャンセルを保証することはできない.さらに悪いことに、タスクが永遠に終了しない可能性がある.第2種類は利用の中断メカニズムであり、JVMはブロック方法で中断の速度を検出することを保証することはできないが、実際には非常に速い.インスタンス1(キャンセルフラグを使用すると、キャンセルされたタスクがまだ実行中であり、再検出フラグタスクが実行されている場合にのみキャンセルされることがわかります)タスクは次の素数を取得し続け、素数を取得するたびにsleepを使用して素数を取得する時間は約10 sです.
package org.thread;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class PrimeGenerator extends Thread {

    private final List<BigInteger> primes=new ArrayList<BigInteger>();
    private volatile boolean cancelled;
    @Override
    public void run() {
        // TODO Auto-generated method stub
        BigInteger p=BigInteger.ONE;
        while(!cancelled){
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            p=p.nextProbablePrime();
            synchronized (this) {
                primes.add(p);
            }
        }
        
    }
    public void cancell(){cancelled=true;};
    public synchronized List<BigInteger> get(){
        return new ArrayList<BigInteger>(primes);
    }

}

テストプログラムでは素数取得スレッドを起動した後,1 s後に素数スレッドの取得をキャンセルした結果,スレッドが本当に終了したのは9 s後であり,キャンセルフラグによりスレッドが直ちに終了または終了することは保証されないことが分かった.
package org.thread;

public class InterruptTest {

    public static void main(String[] args) {
        PrimeGenerator t=new PrimeGenerator();
//        PrimeGenerator1 t=new PrimeGenerator1();
        t.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        t.cancell();
        long start=System.currentTimeMillis();
        long end=0;
        while(t.isAlive()){
             end=System.currentTimeMillis();
        }
        System.out.println(end-start);
    }

}

インスタンス2(割り込みキャンセルを使用すると、キャンセルされたタスクがすぐに終了することがわかります)タスクは次の素数を取得し続け、素数を取得するたびにsleepを使用して素数を取得することを保証する時間は約10 sです.
package org.thread;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class PrimeGenerator1 extends Thread{

    private final List<BigInteger> primes=new ArrayList<BigInteger>();
    @Override
    public void run() {
        // TODO Auto-generated method stub
        BigInteger p=BigInteger.ONE;
        while(!Thread.currentThread().isInterrupted()){
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                Thread.currentThread().interrupt();
                e.printStackTrace();
            }
            p=p.nextProbablePrime();
            synchronized (this) {
                primes.add(p);
            }
        }
        
    }
    public void cancell(){interrupt();};
    public synchronized List<BigInteger> get(){
        return new ArrayList<BigInteger>(primes);
    }

}

テストプログラムで素数を取得するスレッドを起動した後,1 s後に素数スレッドの取得をキャンセルした結果,スレッドは直ちに終了できることが分かった.
package org.thread;

public class InterruptTest {

    public static void main(String[] args) {
//        PrimeGenerator t=new PrimeGenerator();
        PrimeGenerator1 t=new PrimeGenerator1();
        t.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        t.cancell();
        long start=System.currentTimeMillis();
        long end=0;
        while(t.isAlive()){
             end=System.currentTimeMillis();
        }
        System.out.println(end-start);
    }

}