1

特定のタスクを別のクラスで実行するためのスレッドを作成しようとしています。スレッドはタスクを開始していますが、スレッドを停止しようとしても停止しません。スレッドはループまで続きます。助けてください。

スレッド クラス:

package com.development;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ThreadExample extends JFrame {
    MyThread mt;
    Thread th;
    ThreadExample(){        
        JPanel p1 = new JPanel();
        p1.setPreferredSize(new Dimension(400,400));
        JButton b1 = new JButton("Start");
        JButton b2 = new JButton("Stop");
        b1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                  mt = new MyThread();
                  th = new Thread(mt);
                 th.start();
            }
        });
        b2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                th.interrupt();               
            }
        });
        p1.add(b1);
        p1.add(b2);
        this.getContentPane().add(p1);
        this.pack();
        this.setVisible(true);
    }
    public static void main(String arg[]) {
        ThreadExample mt = new ThreadExample();
        mt.setVisible(true);
    }
    public class MyThread implements Runnable{
        private volatile boolean runnable=true;
        DisplayMsg dm = new DisplayMsg("Cycle");
        @Override
        public void run() {
            while(!Thread.currentThread().isInterrupted()) {
            // TODO Auto-generated method stub
               dm.show();                 
            }    
        }
    }    
}


DisplayMsg class:

package com.development;

public class DisplayMsg {
    private String dispMsg; 
    private boolean runnable;
    DisplayMsg(String dispMsg){
        this.dispMsg=dispMsg;
    }
    public void show() {
        for(int t=0;t<100;t++) {        
        try {
            System.out.println(dispMsg + t);
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        }
    }   
}
4

4 に答える 4

7

DisplayMsg クラスは 100 秒間ループし、割り込みを無視します。実際、Thread.sleep()が中断されると、割り込みステータスをリセットしてから、InterruptedException をスローします。InterruptedException を無視するため、スレッドは何も起こらなかったかのように続行します。

public void show() {
    for(int t=0;t<100;t++) {        
        try {
            System.out.println(dispMsg + t);
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

割り込みを無視しない:

public void show() {
    for(int t=0;t<100;t++) {        
        try {
            System.out.println(dispMsg + t);
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // re-interrupt the thread and stop looping
            Thread.currentThread().interrupt();
            return;
        }
    }
}
于 2013-07-30T14:08:24.337 に答える
1

クラスでをキャッチするInterruptedExceptionDisplayMsg、中断フラグがリセットされます。

例外をキャッチすることは問題ありませんが、後でスレッドが中断されたかどうかを知る必要がある場合はThread.currentThread.interrupt();、その catch ブロックで再度中断してフラグをリセットし、ループ/リターンから抜け出す必要があります。

于 2013-07-30T14:08:39.927 に答える
1

必要なものを実現するはるかに単純な設計は次のとおりです。

public class MyThread implements Runnable{
    DisplayMsg dm = new DisplayMsg("Cycle");
    @Override public void run() {
        try { while(true) dm.show(); } 
        catch (InterruptedException e) { }
    }
}    

public class DisplayMsg {
  ...
  public void show() throws InterruptedException {
    for(int t=0;t<100;t++) {        
      System.out.println(dispMsg + t);
      Thread.sleep(1000);
    }
}   

}

これにより、自分で努力することなく、単純に がInterruptedException伝播して終了します。MyThread

于 2013-07-30T15:16:27.490 に答える
0

何が起こっているかは、スリープする前に !Thread.currentThread().isInterrupted() をチェックする必要があると思います。メソッドで show() を呼び出しています。これは 100 秒間反復し、while ループはスレッドが中断されたかどうかを確認します。interrtuped のチェックを show メソッドに移動し、interrupted フラグが表示されるかどうかを確認します。次の回答に従って、InterruptedException をキャッチするときに Thread interrupted フラグも設定する必要があります。

于 2013-07-30T14:10:01.400 に答える