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

实现您需要的更简单的设计如下:

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 回答
1

当您InterruptedExceptionDisplayMsg课堂上捕获时,中断标志被重置。

捕获异常很好,但是如果您随后需要知道线程是否已被中断,则需要通过Thread.currentThread.interrupt();在该 catch 块中再次中断并跳出循环/返回来重置标志。

于 2013-07-30T14:08:39.927 回答
0

我相信正在发生的事情是您需要在每次睡眠之前检查 !Thread.currentThread().isInterrupted() 。您在将迭代 100 秒的方法中调用 show(),然后您的 while 循环将检查线程是否被中断。将您的 interrtuped 检查移至您的 show 方法,看看它是否看到中断标志。根据下一个答案,您还应该在捕获 InterruptedException 时设置线程中断标志。

于 2013-07-30T14:10:01.400 回答