让Java程序在没有线程的情况下休眠

13

我有一个Java程序,它执行一些计算,然后将结果上传到MYSQL数据库(托管在同一网络中的另一台计算机上)。有时候我会遇到这样的问题,即程序计算速度比上传速度快,因此无法上传所有结果。该程序目前没有线程。

是否有一种方法可以使程序在完成计算后暂停几毫秒,以便上传能够正常进行。(就像其他语言中的sleep或wait函数)

我可以将程序线程化,但那将需要大量重写。有更简单的方法吗?

谢谢


4
我很好奇单线程程序如何比其他程序更快地完成一件事情,但由于时间问题导致失败。如果是单线程,这些操作就是连续的。你是否在使用某个库或其他以不同线程工作的东西来上传?如果确实是单线程,这种情况实际上是没有意义的。 - Robin
@Robin:我认为唯一可能的方法是如果Ankur的应用程序正在注册或执行某种异步进程。单线程应用程序可能处于被某些异步事件中断的单个逻辑线程中。不过,Sleep不应该是解决问题的首要想法。 - Paul Sasik
我在我的程序中使用第三方API。它们可能会在程序中创建线程,从而导致异步问题。 - Ank
如果你刚刚粘贴了你的代码,我们很可能能够看出真正的问题所在。我有点怀疑你是否与使用jdbc相关的任何异步操作。你还使用了哪些第三方API? - Blake Pettersson
8个回答

11

有没有办法让程序在完成计算后睡眠几毫秒,以便上传可以正常进行。 (就像其他语言中的睡眠或等待函数)

Thread.sleep(milliseconds)是一个公共静态方法,适用于单线程程序。以下是一个典型的模式:

try {
    // to sleep 10 seconds
    Thread.sleep(10000);
} catch (InterruptedException e) {
    // recommended because catching InterruptedException clears interrupt flag
    Thread.currentThread().interrupt();
    // you probably want to quit if the thread is interrupted
    return;
}

不需要实现Runnable或对线程调用进行任何其他操作。 您可以随时调用它来在某些代码中暂停。


我应该在我的主类中实现Runnable吗? - Ank

9

您不需要重新线程或进行任何类似的操作。您只需要调用:

Thread.Sleep(5000); // pause the app for 5 seconds

每个应用程序也是一个线程,在你的情况下也被称为单线程应用程序。你可以使用像Sleep这样的线程API,而不需要任何其他代码或重构。
但是要注意:如果你需要使用Thread.Sleep来管理控制流,那么架构上可能出了一些问题。从你的OP中我担心的是,在你描述的单线程应用程序中,似乎有一个操作“超前”了另一个操作。这是不可能的,除非你从其他地方接收异步事件。
另一个警告是:Sleep需要一个毫秒级别的参数,通常是任意的,只是意味着“等一会儿”。问题在于,“一会儿”可能今天没问题,但明天你的机器负载会更大,“一会儿”就不再足够好,你的Sleep会过期,同样的错误会出现。当然,你可以将超时设置为“很长时间”,但这样你就需要“很长时间”等待每个交易...进退两难。

3
@Ankur: 请看我的最新编辑。Thread.Sleep通常用于解决时间问题的hack。如果代码全部是你自己写的,那么时间问题很可能是你自己造成的。也就是说,Sleep可以用于处理第三方API和服务中无法控制的问题,但如果你拥有代码,请不要过快地使用它。 - Paul Sasik
我拥有这段代码,但是其中使用了MySQL API和另一个第三方API。你建议使用Thread.Sleep()吗? - Ank
1
所以你并不拥有(没有创建)所有的代码。你依赖于他人的代码。即便如此,我无法在看到更多问题之前推荐使用Sleep。我建议在使用Sleep之前先尝试找出为什么会出现不同步的情况。 - Paul Sasik
大多数情况下,该程序会将所有内容都写入数据库,但最近我注意到该程序在向数据库写入时随机地省略了部分条目。我已检查了我的数据库是否存在问题,一切都正常。我有点确定这正是发生的事情。 - Ank
2
如果我是你,我会这样做:先拿一个基准样本来检测问题。例如,今天和明天有多少遗漏的条目?然后加入Sleep(5000)并记录事件数量。评估差异。如果差异显著,则尝试使用日志记录和其他故障排除方法解决问题,不要将Sleep作为救命稻草。如果差异很小,则除了时间问题还有其他问题。 - Paul Sasik
显示剩余3条评论

3

使用 Thread.sleep()

try
{
    Thread.sleep(1000); // Sleep for one second
}
catch (InterruptedException e)
{
    Thread.currentThread().interrupt();
}

这不会在程序中引入新的Thread,也不需要任何其他与Thread相关的机制。


提醒:如果你捕获到InterruptedException异常,建议调用Thread.currentThread().interrupt();。参考链接:https://dev59.com/tm445IYBdhLWcg3wWY8U - Gray

1

只需使用:

try
{
Thread.sleep(<time in ms>);
}
catch(InterruptedException ex}
{
}

这将使当前线程(例如主线程)休眠。


我应该在我的主类中实现Runnable吗? - Ank
1
不需要实现Runnable接口。上面的代码调用了一个静态方法来暂停一段时间,该方法恰好在Thread类中。这实际上并没有使你的代码多线程化。 - Martin
1
@Ankur 不,Thread.sleep() 只是一个普通的静态方法,它的命名不太合适,因为它与线程无关。 - Joachim Isaksson
2
FYI:如果您捕获 InterruptedException,建议调用 Thread.currentThread().interrupt();。请参阅:https://dev59.com/tm445IYBdhLWcg3wWY8U - Gray
@Gray:谢谢你提醒我,我之前并没有意识到这一点。 - Martin

0

java.lang.Thread类中的静态方法sleep()在被调用时会暂停当前线程,这可能是主线程。您无需进行任何特殊操作即可使用它。


0
每个Java应用程序都在JVM中的一个线程中执行。调用静态方法Thread.sleep将会导致您的应用程序线程(正在运行的线程)停止。

0

你的程序不是多线程的...但它正在使用一个线程。Thread.Sleep仍然可以工作。


0

在计算完成后,您可以使用Thread.sleep();而无需使用线程重写整个程序!


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