Java 命令行应用程序在不占用资源的情况下进行后台工作的正确方法是什么?它应该在循环中使用 sleep() 还是有更优雅/有效的方式?
Francisco Canedo
问问题
2650 次
4 回答
9
一些启发式:
- 不要试图在您的应用程序中做出调度决定。操作系统的调度程序比你的要好得多。让它完成它的工作。
- 如果没有必要,请不要投票。例如,不是睡n秒,然后醒来检查一个未阻塞的套接字,而是阻塞套接字。第二种策略与操作系统的调度程序配合得更好。
- 如果没有必要,不要使用巨大的堆,并且尽量不要一次分配巨大的内存块。抖动应用程序往往会对系统性能产生负面影响。
- 使用缓冲 I/O。总是。如果您认为您需要非缓冲 I/O,请确保您是对的。(你可能错了。)
- 不要产生很多线程。线程非常昂贵;超过某个点,更多线程会降低应用程序的性能。如果您同时有很多工作要做,请学习和使用
java.util.concurrent
.
当然,这只是一个入门列表......
于 2009-01-13T19:54:51.373 回答
3
如果没有工作要做,我只会使用 sleep() 。例如,如果您正在执行诸如定期轮询任务队列之类的事情并且那里没有任何内容,请睡眠一段时间然后再次检查,等等。
如果您只是想确保不占用 CPU,但您仍在做实际工作,您可以定期调用 Thread.yield()。这将放弃对 CPU 的控制并让其他线程运行,但不会让您进入睡眠状态。如果其他进程不需要 CPU,您将获得控制权并继续工作。
您还可以将线程设置为低优先级: myThread.setPriority(Thread.MIN_PRIORITY);
正如以实玛利所说,不要在你的主线程中这样做。而是创建一个“工作线程”。这样您的 UI(GUI 或 CLI)仍然会响应。
于 2009-01-13T19:41:12.650 回答
2
有几种方法。我会使用 ExecutorService... 例如:
ExecutorService service = Executors.newCachedThreadPool();
Callable<Result> task = new Callable<Result>() {
public Result call() throws Exception {
// code which will be run on background thread
}
};
Future<Result> future = service.submit(task);
// Next line wait until background task is complete
// without killing CPU. Of course, you can do something
// different here and check your 'future' later.
//
// Note also that future.get() may throw various exceptions too,
// you'll need to handle them properly
Result resultFromBackgroundThread = future.get();
这是 Java 5 代码,ExecutorService、Callable、Future 等都在java.util.concurrent
包中。
于 2009-01-13T20:07:53.830 回答
1
一个起点是确保只使用那些资源而没有其他对象(以便它们成为垃圾收集器)。
将 sleep() 放在单线程应用程序中只会停止当前线程。如果您尝试完成在后台处理的数据,而信息仍需要呈现给用户,那么最好将后台进程放在单独的线程中。
于 2009-01-13T19:33:49.530 回答