1

私はJavaのスレッドについて学んでおり、以下のプログラムを持っています。ThreadA の while threadA 条件チェックは、私が期待するほど頻繁には当てはまらないようです。コンソール ウィンドウに表示される唯一の println ステートメントには、100 より大きい i 変数が含まれています。それは、待っていてゆっくりとコンソールに出力されているように見えます。これは1秒ほどで完了すると思います。私は明らかにここで何かを誤解しています.ThreadTesterが100回印刷されない理由についてのアイデアはありますか?

public class ThreadTester {
    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        threadA.start();
    }
}

public class ThreadA extends Thread{
    private volatile Thread threadA = Thread.currentThread();

    public void run() {
        while(threadA == Thread.currentThread()){
            for(int i=0; i<100; i++){
                System.out.println("ThreadA " + i);
            }
        }
    }

    public void stopThread(){
        threadA = null;
    }
}

出力例:

ThreadA 120
ThreadA 121
ThreadA 122
ThreadA 123
ThreadA 124
ThreadA 125
ThreadA 126
ThreadA 127
ThreadA 128
ThreadA 129
ThreadA 130
ThreadA 131
ThreadA 132
ThreadA 133
ThreadA 134
ThreadA 135
ThreadA 136

スレッドを強制終了する方法

クラス Thread には、現在のスレッドを強制終了する方法を知っているはずの stop() メソッドがあります。しかし、オブジェクト インスタンスの不適切なロックおよびロック解除によって、プログラム内の一部のオブジェクトが一貫性のない状態になる可能性があるため、何年も前に廃止されました。

スレッドを強制終了するには、さまざまな方法があります。そのうちの 1 つは、スレッド上に独自のメソッド (stopMe() など) を作成することです。このメソッドでは、独自のブール変数 (stopMe など) を false に設定し、スレッドのメソッド run() 内で定期的にその値をテストします。アプリケーション コードが stopMe の値を true に設定する場合は、メソッド run() でコードの実行を終了するだけです。コード リスト 20-10 では、メソッド run のループが変数 stopMe の値をチェックします。変数 stopMe は、現在の Thread オブジェクトへの参照で初期化されます。変更されるとすぐに (この場合は null に設定されます)、処理が完了します。

変数 stopMe は volatile キーワードで宣言されています。このキーワードは、別のスレッドがそれを変更できること、およびこの変数をレジスタにキャッシュしてはならないことを Java コンパイラに警告するため、すべてのスレッドが常に新しい値を参照する必要があります。

必要に応じてスレッドを強制終了できるように、スレッドを構築する方法に関するサンプル コードを予約します。

 class KillTheThread{
               public static void main(String args[]){
               Portfolio4 p = new Portfolio4("Portfolio data");
             p.start();

             // Some other code goes here,
             // and now it's time to kill the thread
             p.stopMe();

               }
    }
class Portfolio4 extends Thread{

private volatile Thread stopMe = Thread.currentThread();

    public void stopMe() {
        stopMe = null;
    }

    public void run() {
        while (stopMe == Thread.currentThread()) {
          try{
            //Do some portfolio processing here
          }catch(InterruptedException e ){
            System.out.println(Thread.currentThread().getName()
                                        + e.toString());
        }

     }
 }
4

2 に答える 2

3

threadAフィールドは、オブジェクトが現在のスレッドになる前にメイン スレッドによって初期化されるためThreadA、その値はメイン スレッドに設定されます。ループが実行されると、ThreadAこれが現在のスレッドであるため、反復は発生しません。Eclipse を再起動する前に得られた奇妙な出力は、Eclipse が以前のバージョンのコードを実行しているためである可能性があります。

于 2013-07-06T23:31:27.350 に答える
1

1.
これは、ThreadA がメイン スレッドである場合にのみ機能します。

2.
stopMe() にはもっと簡単な方法があります。

private volatile boolean stopped = false;
public void stopMe() {
    stopped = true;
}
public void run() {
    while (!stopped) {
        // ...
    }
}

3.
「スレッドのキル方法」について。使用できますThread.interrupt()
実際、作業中のスレッドを停止するためにFutureTask.cancel()使用します。Thread.interrupt()

しかし、interrupt() の呼び出しは、実際にはスレッドにシグナルを送信するだけです。スレッドは、シグナルに応答するために追加の作業を行う必要があります。それだけでは止まりません。

InterruptedException最終的にはとをチェックする必要がありますがThread.isInterrupted()、基本的には と同じstopMe()です。

于 2013-07-07T04:15:26.647 に答える