4

我开发了一个代码,将在执行时启动两个线程

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 那么我将如何做请告知,因为停止线程意味着它的运行方法已完成但我想停止它有力地我将如何做到这一点,请告知

4

3 回答 3

4

免责声明:这个答案有一个教程字符。

基本方法:我们最初保持简单,不处理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

    ...
  }
}

评论: 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 毫秒。但是,一般来说,如果您的代码必须执行改变变量状态的操作(特别是,如果这些变量在多个线程之间共享!),这样您就不会让这些变量处于不正确的状态。实际上,由于您控制了终止,因此您可以正确处理事务。这显然假设,在循环的每次迭代结束时,变量状态是一致的。

现在让我们改进处理期间中断的基本方法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.sleep通话过程中打断,那么你不需要做任何事情,除了处理InterruptedException来清理你的状态,如果有必要的话。相反,如果您需要在“慢”代码期间中断,则必须this.isInterrupted()在您喜欢的任何地方(可能在多个地方)调用并中断循环;循环条件内的调用很常见但不是必需的。

更多信息可以在 Java 并发中断教程中找到。

于 2012-04-29T11:28:52.540 回答
2

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

Java 并发教程中有关这方面的更多信息。

于 2012-04-29T11:38:43.937 回答
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();
    }
}
于 2012-04-29T13:46:01.113 回答