在某个条件下正确终止线程的方法是什么?

4

一些线程在其run方法中执行一系列操作。当车站关闭时,它通过onStationClosed通知所有乘客。当发生这种情况时,线程必须执行某些操作(例如离开站点),并且线程必须在未完成所有剩余操作的情况下终止。

正确的方法是什么:

// 1 - By checking station's state between each operationN?

public class Passenger extends Thread
{
     Station station;
     public void onStationClosed()
     {
          // Do some action before thread terminates
     }
     @Override
     public void run()
     {
         operation1();
         if(station.getState == Station.Closed) return;
         operation2();
         if(station.getState == Station.Closed) return;
         operation3();
         if(station.getState == Station.Closed) return;
         ..
         operationN();
     }
}

// 2 - Throw StationClosedException from onStationClosed and catch it in Station.

public class Passenger extends Thread
{
    Station station;
    public void onStationClosed()
    {
         // Do some action before thread terminates
         throw new StationClosedException();
    }
    @Override
    public void run()
    {
        operation1();
        operation2();
        ..
        operationN();
    }
}

你可以创建一个栈来保存操作(这需要是一个具有operation()方法的接口),然后在while循环中迭代,但要在循环开始时检查站点状态。 - Hovercraft Full Of Eels
2
在编程中,使用异常来控制流程总是不好的,异常应该只用于异常情况。我认为第一个观点很有趣,但仍不够理想。您能详细解释一下问题吗?为什么需要线程?为什么不能使用回调来向工作线程发出信号,表明某个站点已关闭,不再需要继续工作? - Maurício Linhares
我有车站和乘客。乘客前往车站并试图进入车站。乘客在车站内完成他们需要做的事情,一旦车站关闭,即使他们没有完成所有计划中的事情,他们也需要离开。 - theateist
1个回答

2
第一个解决方案相当不错。然而,它并不是非常。考虑将操作封装在一些小的动作对象中,在执行每个操作之前检查station状态:
List<Operation> operations = Arrays.asList(new Operation1(), new Operation2(), new Operation3());

for(Operation operation: operations) {
  if(!perform(operation)) {
    return;
  }
}

其中perform()的定义如下:

private boolean perform(Operation operation) {
  if(station.getState == Station.Closed)
    return false;
  operation.run();
  return true;
}

有点牵强,但当操作数量增加时,您会感激它。
我不太理解这个异常解决方案。如果您从onStationClosed()回调中抛出该异常,它将被抛回到您的事件发送线程,而不是Passenger线程。它不会中断您的线程。
但是,您可以使用InterruptedException来控制此流程。这个解决方案与检查站点状态非常相似,但是您要检查Thread.isInterrupted()标志。额外好处:I/O操作和睡眠会自动中断。您只需要调用
Thread passenger = new Passenger();
passenger.interrupt();

1
使用 InterruptedException 是正确的做法,因为一旦你添加了 I/O 操作,你就需要捕获这些异常。 - user949300
1
请注意,由于您在一个线程中更新了 Station 的状态并在另一个线程中使用它,因此您需要对 Station 进行同步。 - Ravi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接