停止Thread的单个实例

时间:2014-05-20 18:49:59

标签: java multithreading cancellation

我有两个连续运行的线程实例。我怎么能停止线程的第一个实例。请找到以下代码: -

public class Thread1 extends Thread {

 static volatile boolean bThreadStop = false ;  

  public void run() {
    while(!bThreadStop) {
      System.out.println("THREAD1");
      //BUSINESS LOGIC//

    }
  }
 public static void main(String[] args) {
   Thread1 t1 = new Thread1();
  t1.start();

      Thread1 t2 = new Thread1();
  t2.start();

  }
}

根据上面的例子,我需要停止Thread1的t1实例。请建议我如何实现同样的目标。

4 个答案:

答案 0 :(得分:1)

你的问题的直接答案是你的标志是静态的,所以你的Thread子类的所有实例都看到相同的标志;使其成为实例范围而不是静态意味着可以单独停止各个线程对象。同时使标志为volatile将意味着对Thread子类实例可以看到对标志的更新。如果没有volatile,JVM可以优化标记检查。

但是使用你自己的旗帜取消线程并不是一个好主意。这里有一个非常好的标志,已经为你制作并融入了Thread类。事实上,它比你想出的任何东西都要好,因为你的线程无法停止睡眠或等待检查你自己的旗帜,所以一旦你设置它,线程可能需要一段时间才能响应。但是如果你使用中断设施,那么线程可以检查自己的中断标志并立即停止睡眠或等待。

这是您重复使用中断的示例。在您的示例中,输出不区分Thread1和Thread2,我添加了一个名称来帮助它。此外,我为线程添加了一个睡眠(为了减少写入控制台的内容量以及演示中断睡眠线程),并且在等待足够长的时间后,示例也取消了第二个线程。明确哪个主题被取消了。

public class Thread1 extends Thread {

    public Thread1(String name) {
        super(name);
    }

    public void run() {
        try {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println(getName());
                //BUSINESS LOGIC//
                Thread.sleep(1000L);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("thread " + getName() + " woke up");
        }
        System.out.println("thread " + getName() + " finished");
    }

    public static void main(String[] args) throws Exception {
        Thread1 t1 = new Thread1("t1");
        t1.start();
        Thread1 t2 = new Thread1("t2");
        t2.start();
        Thread.sleep(5000L);
        t1.interrupt();        // cancel the first thread
        Thread.sleep(5000L);
        t2.interrupt();        // cancel the second thread
    }
}

输出如下:

t1
t2
t1
t2
t2
t1
t2
t1
t2
t1
thread t1 woke up
thread t1 finished
t2
t2
t2
t2
t2
thread t2 woke up
thread t2 finished

我还有另一个线程中断示例,其中包含更多详细信息here

答案 1 :(得分:0)

如何将bThreadStop标记为实例变量而不是使其变为静态?

答案 2 :(得分:0)

您的bThreadStop变量会停止所有正在运行的线程。如果你把它变成一个实例变量(甚至更好,添加一个setter方法),你就可以说t2.stop()并且只停止t2

查看我对How to find and stop all currently running threads?的回答,以及有关如何正确停止线程的其他讨论。

通过该讨论,StoppableRunnable以干净,线程安全的方式提供您正在寻找的行为:

public abstract class StoppableRunnable implements Runnable {
    private volatile boolean stopWork;
    private boolean done;

    public final void run() {
        setup();
        while(!stopWork && !done) {
            doUnitOfWork();
        }
        cleanup();
    }

    /**
     * Safely instructs this thread to stop working,
     * letting it finish it's current unit of work,
     * then doing any necessary cleanup and terminating
     * the thread.  Notice that this does not guarentee
     * the thread will stop, as doUnitOfWork() could
     * block if not properly implemented.
     */
    public void stop() {
        stopWork = true;
    }

    protected void done() {
        done = true;
    }

    protected void setup() { }
    protected void cleanup() { }

    /**
     * Does as small a unit of work as can be defined
     * for this thread.  Once there is no more work to
     * be done, done() should be called.
     */
    protected abstract void doUnitOfWork();
}

答案 3 :(得分:0)

正如您所看到的,有很多答案。我粘贴了我的贡献:

public class Thread1 extends Thread {

private volatile boolean threadRunning = true;  
private final int id;

public Thread1 (int id){
    this.id = id;
}

public void run() {
   while(threadRunning) {
       System.out.println("THREAD" + id);
   } 
}

public void stopTheThread(){
     threadRunning = false;
}

public static void main(String[] args) {
    Thread1 t1 = new Thread1(1);
    Thread1 t2 = new Thread1(2);

    t1.start();
    t2.start();

    t2.stopTheThread();
    t1.stopTheThread();
  }
}

我也喜欢基于捕获InterruptedException的Nathan Hughes实现。