关于停止线程

时间:2012-04-29 11:24:17

标签: java

我开发了一个代码,它将在执行

时启动两个线程
public class MyThread1 extends Thread //extend thread class 
{
    // public  synchronized void run()
     //synchronized (this)

     public   void run()
    {//synchronized(this)
        //{
         for(int i=0;i<20;++i) {
             try{
                 Thread.sleep(500);


          System.out.print(i +"\n"+ "..");
             }catch(Exception e)
             {e.printStackTrace();}
          //} 
        }

     }  

 public static void main(String... a) 
 {
     MyThread1 t = new MyThread1();

     Thread x = new Thread(t);

     Thread y = new Thread(t);
     x.start();
     y.start();

     }

现在它启动两个线程,但如果我想停止一个特定的线程,让我说我想停止线程Y然后我将如何做它请告知,因为停止线程意味着它的运行方法已完成但我想要要强行阻止我这样做,请告知

3 个答案:

答案 0 :(得分:4)

免责声明:这个答案有一个教程角色。

BASIC APPROACH :我们最初保持简单,不处理Thread.sleep方法中的中断。本质上,你应该有一个外部可设置的变量,run方法在循环的每次迭代时检查该变量;然后您可以设置该变量以优雅地终止run()方法。请注意这个成语如何可以很容易地用于Java以外的其他语言。

例如:

public class MyThreadedClass extends Thread {

  private volatile boolean completed = false;

  public void setCompleted() {
    this.completed = true;
  }

  public void run()
  {
    while (!completed) {
      // do anything you fashion
    }
  } 

  public static void main(String... args) 
  {
    MyThreadedClass x = new MyThreadedClass();
    MyThreadedClass y = new MyThreadedClass();

    x.start();
    y.start();

    x.setCompleted(); // will complete as soon as the latest iteration finishes

    ...
  }
}

COMMENTS :volatile标志告诉编译器completed可以(并且将)在run()函数的控制之外进行更改,即另一个线程可能会更改它。否则,根据类的唯一同步行为,可能会错误地优化循环中的迭代检查。

在您run()的特定情况下,我们会利用for循环,因此我们的方法会转化为以下内容:

public void run()
{
  try {
    for(int i=0;i<20 && !completed;++i) {        
      Thread.sleep(500);
      System.out.print(i +"\n"+ "..");
    } 
  } catch(Exception e) {
    e.printStackTrace();
  }
}

评论:很明显,由于睡眠呼叫,您可能需要等待500毫秒。但是,一般来说,如果你的代码必须执行改变变量状态的操作(特别是,如果这些变量在多个线程之间共享!),这样就不会让这些变量处于不正确的状态。实际上,您可以正确处理事务,因为您可以控制终止。这显然假设,在循环的每次迭代结束时,变量state是一致的。

现在让我们改进处理Thread.sleep期间中断的基本方法。

完整的答案:从调用者方面来看,这个答案涉及使用Thread.interrupt()方法,这使得该方法严格地针对Java。

public class MyThreadedClass extends Thread {

  public void run()
  {
    try {
      for(int i=0;i<20 && !this.isInterrupted();++i) {        
        Thread.sleep(500);
        System.out.print(i +"\n"+ "..");
        ...
        // some molassy slow code here, where you may sprinkle isInterrupted()
        // checks and consequent break statements 
      } 
    } catch(InterruptedException e) {
      // do whatever you need to clean things up
    } catch(Exception e) {
      // handle other exceptions as seen fit
    }
  }

  public static void main(String... args) 
  {
    MyThreadedClass x = new MyThreadedClass();

    x.start();

    // will complete 
    // a) as soon as one isInterrupted() check breaks the loop, or 
    // b) "immediately" during the blocking call to sleep()
    x.interrupt(); 

    ...
  }
}

评论:在这种情况下,您已经完成了一半的工作由Thread本身完成。如果您只需要在Thread.sleep呼叫期间中断,那么除非必要,否则您无需执行除InterruptedException之外的任何其他操作来清理您的状态。如果你需要在“慢”代码中断,你必须在任何你喜欢的地方(可能在多个地方)调用this.isInterrupted()并打破循环;循环条件内的调用很常见但不是必需的。

可以在Java Concurrency Interrupts tutorial中找到更多信息。

答案 1 :(得分:2)

你应该interrupt()线程。阻塞调用(如sleep())将在线程中断时抛出InterruptedException。如果要在紧密循环中尽可能快地停止,请定期检查当前线程是否已使用isInterrupted()方法中断。

Java concurrency tutorial中有关此内容的详细信息。

答案 2 :(得分:2)

尽可能保持简单。

 public class Threads {
    public static class MyRunnable implements Runnable {
        public void run() {
            try {
                for (int i = 0; i < 20; ++i) {
                    Thread.sleep(500);
                    System.out.print(i + "\n" + "..");
                }
            } catch (InterruptedException e) {
                System.out.println("Interrupted");
            }
        }
    }

    public static void main(String... a) throws InterruptedException {
        Thread x = new Thread(new MyRunnable());
        Thread y = new Thread(new MyRunnable());
        x.start();
        y.start();
        Thread.sleep(2000);
        y.interrupt();
        Thread.sleep(2000);
        x.interrupt();
    }
}