有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java我应该有一个专用线程来监视超时吗?

现在我有两个线程在我的程序中运行。一个不断尝试从用户那里读取输入,另一个观察超时。如果用户在给定的时间内没有发送任何输入,则会发生超时。这两条线如下所示:

用户输入线程

while(true){
    if(in.hasNextLine()){
        processLine(in.nextLine());
        timeLastRecieved = System.currentTimeMillis();
    }
}

超时线程

while(true){
    //Check for a timout
    if(timeLastRecieved+timeoutDuration <= System.currentTimeMillis())
        timeUserOut();

    else{
        //Sleep until it is possible for a timeout to occur
        Thread.sleep((timeLastSent+timeoutDuration) - System.currentTimeMillis());   
    }
}

现在我已经把这些线分开了,但我可以这样组合它们

while(true){
    if(in.hasNextLine()){
        processLine(in.nextLine());
        timeLastRecieved = System.currentTimeMillis();
    }

    //Check for a timout
    if(timeLastRecieved+timeoutDuration <= System.currentTimeMillis())
        timeUserOut();
}

但我真的不需要经常检查超时。所以,我应该经常组合线程并检查超时,还是应该有两个线程。我不担心性能,因为我是正确的编码礼仪。如果这意味着什么的话,超时时间大约为15分钟

编辑:只是想指出,在有两个线程的版本中,我在睡觉,但在组合版本中,我从来没有睡过线程。这显然会导致检查超时的if语句运行得比需要的时间更长


共 (2) 个答案

  1. # 1 楼答案

    您需要有两个线程——一个线程等待数据通过InputStream/Reader传入,另一个线程正在观察时间,以确定时间是否过长。使用1个线程的唯一方法是休眠一段超时时间,然后定期轮询数据。但这比使用一个单独的线程专门从InputStream/Reader读取数据效率要低

    您可能希望签出Timeout作为实现超时的通用选项

  2. # 2 楼答案

    总结一下我的评论:我认为没有必要用单独的线程来检查超时情况

    原因:

    • 你需要在他们之间共享像timeLastRecieved这样的信息,这可能比你想要的更复杂(例如,在某些情况下,对long值的访问不是原子的)
    • 根据您的描述,轮询用户输入和超时(没有及时提供输入)似乎密切相关,因此轮询线程也可以检查超时。这并不意味着它也必须处理超时,只是在某个地方报告或调用某个超时处理程序可能是更好的设计
    • 因为更新timeLastRecieved和检查超时是在同一个地方处理的,所以更容易阅读和理解
    • 由于不需要线程间通信或协调(没有需要通信的线程),因此它可能也更健壮

    关于检查超时的一些提示:

    • 在更新timeLastReceived时,应该计算超时阈值,然后只检查当前时间,而不是在每次迭代中计算它
    • 在处理输入之前,您可能需要计算超时阈值,以避免它也依赖于处理时间

    最后,还有一些替代方法,比如使用java.util.Timer。在这里,您可以简单地安排一个超时任务,该任务将在超时发生时执行。然后,该任务将检查超时是否真的发生,如果没有,它将返回

    要在超时发生之前处理新输入,至少可以使用两种方法:

    • 取消当前的超时任务,将其从计时器中删除,并安排一个新的超时任务
    • 如果已经有计划的超时任务,则不要计划新的超时任务,而是等待当前任务运行。然后,当前线程检查超时,如果没有超时,它会为当前预期的超时安排一个新任务(或其本身)(请注意,这需要一些线程间通信,所以在这里要小心)