2

我已经按顺序启动了线程,但我不知道如何以相反的顺序停止它们。例如:它们是这样开始的:A->B->C->D 我希望它们停止:D->C->B->A 我根本不知道如何停止线程,甚至在这个命令。我感谢任何帮助或建议。

import java.util.*;

class Service extends Thread
{
  private RobotController controller;
  private String robotID;
  private byte[] lock;                                          

  public Service(RobotController cntrl, String id)
  {
    controller = cntrl;
    robotID = id;
  }

  public byte[] getLock() { return lock;}                                                              
  public void run()
  {
    lock = new byte[0]; 
    synchronized(lock)                                          
    {

      byte[] data;
      while ((data = controller.getData()) == null)
      {
        try {
          lock.wait();  
        } catch (InterruptedException ie) {}
      }
      System.out.println("Robot " + robotID + " Working");
    }
  }
}

class RobotController
{
  private byte[] robotData;
  private Vector threadList = new Vector();                      
  private Service thread_A;
  private Service thread_B;
  private Service thread_C;
  private Service thread_D;
  private volatile boolean done;

  public void setup(){
    thread_A = new Service(this, "A");
    thread_B = new Service(this, "B");
    thread_C = new Service(this, "C");
    thread_D = new Service(this, "D");
    threadList.addElement(thread_A);                               
    threadList.addElement(thread_B);                                
    threadList.addElement(thread_C);                                
    threadList.addElement(thread_D);                                
    thread_A.start();
    thread_B.start();
    thread_C.start();
    thread_D.start();
    start();
    stop();

  }

  public void start()
  { 
      System.out.println("Thread starts");
      {
            for (int i=0; i <= 3; i++)                                    
            {
              try {
                Thread.sleep(500);
              }catch (InterruptedException ie){}
              putData(new byte[10]);
              Service rbot = (Service)threadList.elementAt(i);               
              byte[] robotLock = rbot.getLock();                        
              synchronized(robotLock) {                                     
                robotLock.notify();                                      
              }
            }
      }
  }

  public void stop()
  {
      {

      }
  }

  public synchronized byte[] getData()                          
  {
    if (robotData != null)
    {
      byte[] d = new byte[robotData.length];
      System.arraycopy(robotData, 0, d, 0, robotData.length);
      robotData = null;
      return d;
    }
    return null;
  }

  public void putData(byte[] d) { robotData = d;}

  public static void main(String args[])
  {
    RobotController controller = new RobotController();
    controller.setup();
  }
}
4

4 回答 4

2

cancel()如果我想显式终止它们,我通常会在我的线程中包含类似方法的东西。

class Service extends Thread {
    private volatile boolean cancel = false;

    public void cancel() {
        cancel = true;
    }

    public void run() {
        ...
        while (!cancel && (data = controller.getData()) == null) {
        ...
        }
    }
}

按照 mre 的建议,将线程保存在堆栈中,然后从堆栈中弹出并调用cancel,然后interrupt在每个线程上调用。

于 2013-06-04T15:12:52.337 回答
2

我已经按顺序启动了线程,但我不知道如何以相反的顺序停止它们。

这很难做到。您可以通过设置volatile关闭布尔值或中断它们来停止线程,但是这些机制都不能保证立即停止线程。

您当然可以List<Thread>在构建它们时保留一个,Collections.reverse(threadList)然后依次调用thread.interrupt()每个。如果您必须让他们按顺序完成,那么您应该中断()他们然后加入他们。就像是:

 Collections.reverse(threadList);
 for (Thread thread : threadList) {
      thread.interrupt();
      thread.join();
 }

然后每个线程应该做类似的事情:

 while (!Thread.currentThread().isInterrupted()) {
     ...
 }

请注意,如果您正在运行Thread.sleep(...)或其他方法 throw InterruptedException,则需要重新启用中断标志:

  try {
      Thread.sleep(...);
  } catch (InterruptedException e) {
      // by convention if InterruptedException thrown, interrupt flag is cleared
      Thread.currentThread().interrupt();
      ...
  }
于 2013-06-04T15:19:34.657 回答
1

让每个线程保留对要启动的下一个线程的引用。然后每个线程可以定期检查线程是否还活着。如果不是,该线程应该终止。当它发生时,前一个线程将通知并终止,依此类推。

abstract class ChainThread extends Thread {

  private final Thread next;

  ChainThread(Thread next) { this.next = next; }

  @Override
  public final void run() {
    next.start();
    while (!Thread.currentThread().isInterrupted() && next.isAlive()) {
      do();
    }
  }

  abstract void do();

}
于 2013-06-04T15:49:28.710 回答
0

如果我Service正确阅读了代码,它会等到有数据可以执行,然后完成。因此,您实际上并不需要显式stopcancel类型信号,线程将在它们工作后自行终止。

要强制关闭顺序,您可以让每个人都Service知道前一个Service,然后调用previousService.join(). 假设没有InterruptedExceptions抛出,它们将在看到控制器有数据后按顺序关闭。

以这种方式创建服务:

    Service serviceA = new Service(controller, "A", null);
    Service serviceB = new Service(controller, "B", serviceA);
    Service serviceC = new Service(controller, "C", serviceB);
    Service serviceD = new Service(controller, "D", serviceC);

并且实现被编辑为仅在依赖完成后退出Services

private final RobotController controller;
private final String robotID;
private byte[] lock;
private final Service dependentService;

public Service(RobotController cntrl, String id, Service dependentService) {
    controller = cntrl;
    robotID = id;
    this.dependentService = dependentService;
}

public byte[] getLock() {
    return lock;
}

@Override
public void run() {
    lock = new byte[0];
    synchronized (lock) {

        byte[] data;
        while ((data = controller.getData()) == null) {
            try {
                lock.wait();
            }
            catch (InterruptedException ie) {
            }
        }
        System.out.println("Robot " + robotID + " Working");
    }

    if (dependentService != null) {
        try {
            dependentService.join();
        }
        catch (InterruptedException e) {
            this.interrupt();
        }
    }
}
于 2013-06-04T15:42:21.040 回答