无法停止Java线程

时间:2013-07-30 14:04:04

标签: java multithreading

我正在尝试为另一个类中的特定任务创建一个线程。线程正在启​​动任务,但是当我尝试停止线程时,它没有停止。线程一直持续到循环。你能帮帮我吗?

线程类:

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 个答案:

答案 0 :(得分: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;
        }
    }
}

答案 1 :(得分:1)

当您捕获InterruptedException类中的DisplayMsg时,将重置中断的标志。

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

答案 2 :(得分: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,而不需要自己动手。

答案 3 :(得分:0)

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