我的任务是编写一个小型服务器应用程序。它应该通过控制台启动,然后在后台运行,处理一些网络流量并在本地计算内容,直到收到关机信号。我很确定我可以处理所有这些 - 除了非常基本的应用程序架构。我不确定如何让我的主循环等待应用程序完成。所以这是我当前的代码,清理并省略不必要的部分。
public class TestServer {
public static Logger logger;
private static Boolean abortStartup = false;
private static ServerModule server;
public static void main(String[] args) {
System.out.println("Starting Server...");
initializeServer(); //this function reads config file, and initializes all variables and stuff. If anything goes wrong, abortStartup is set to true
if (!abortStartup) {
runMainLoop();
}
if (!abortStartup) {
cleanup(); //clean up all initialized variables and objects
}
System.out.println("Goodbye.");
}
private static void runMainLoop() {
//This is the main loop. Run this until application terminates.
logger.log(null, "Starting main loop...", Logger.LOGLEVEL_NOTE);
server.run();
while (server.isAlive()) {
//wait until server dies.
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
logger.log(null, "Interrupted during wait for main thread.", Logger.LOGLEVEL_ERROR);
}
}
logger.log(null, "Done.", Logger.LOGLEVEL_NOTE);
}
ServerModule如下所示:
public class ServerModule{
public Boolean shutdown = false;
private Boolean stayAlive = true;
public ServerModule(){
//setup everything
}
public void run() {
//initalize timers, instantiate objects etc.. add listeners and everything. At some point, a network message will set stayAlive to false;
}
public Boolean isAlive() {
return stayAlive;
}
现在提出一个实际的问题:是否有更优雅或更有效的方法来解决这个问题?我具体谈到这个部分:
while (server.isAlive()) {
//wait until server dies.
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
logger.log(null, "Interrupted during wait for main thread.", Logger.LOGLEVEL_ERROR);
}
thread.sleep好吗?我甚至可以省略它吗?我想在我的代码的这一点上等待,所以我可以在执行停止后清理。
答案 0 :(得分:3)
您可以将服务器设为 runnable ,将其打包到线程中并加入!
实施例
my $d = $rep->GetCurrentDiagram();
for my $dl (in $d->DiagramLinks) {
print $dl->Geometry . "\n";
$dl->{Geometry} = 'SX=0;SY=10;EX=0;EY=0;';
$dl->Update();
}
$rep->ReloadDiagram($d->DiagramId);
答案 1 :(得分:3)
此外,您可以将CountDownLatch
用于您的目的,请参阅示例:
public class ServerModule extends Thread {
private final CountDownLatch latch;
ServerModule(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
Thread.sleep(1000L);
//decrease counter of the latch when job is done
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// as ctor arg use threads count for countdown
CountDownLatch latch = new CountDownLatch(1);
System.out.println("Start server");
ServerModule serverModule = new ServerModule(latch);
serverModule.start();
try {
//waiting until latch count will be 0
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Server is done");
}
}
同样使用CountDownLatch
,您可以创建多个服务器实例并在主线程中等待它们,直到它们全部完成。
答案 2 :(得分:1)
这取决于你如何管理你的线程。
在最低级别的Java线程API中,您的主线程可以等待服务器线程完成:
serverThread.join();
查看Thread API以获取更多选项,例如在join()
上设置超时(这样您就可以采取越来越激烈的措施来结束)。
更高级别的线程抽象,例如Executor
,Future
,ForkJoinTask
等,可以为您提供不同API的相同功能。对这些内容的全面探索超出了SO答案的范围 - Oracle提供了有关并发的教程,或者有书籍。