One could employ some sophisticated techniques here. The file watchdog is one option. RMI could be another. But in fact, the mechanisms that are required here are quite simple, so I'd like to propose another (very simple) solution.
Note: This solution is just one option, showing that it is possible to do it that way. It is not a general recommendation, and whether it is "good" or not depends on the application case.
The solution is simply based on Sockets. The ServerSocket#accept
method already encapsulates the functionality that you want:
Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.
Based on this, it is trivial to create such a "remote control": The server just waits for a connection, and sets a flag when the connection is opened:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicBoolean;
class RemoteExitServer
{
private final AtomicBoolean flag = new AtomicBoolean();
RemoteExitServer()
{
Thread t = new Thread(new Runnable()
{
@Override
public void run()
{
waitForConnection();
}
});
t.setDaemon(true);
t.start();
}
private void waitForConnection()
{
ServerSocket server = null;
Socket socket = null;
try
{
server = new ServerSocket(1234);
socket = server.accept();
flag.set(true);
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (server != null)
{
try
{
server.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
if (socket != null)
{
try
{
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
boolean shouldExit()
{
return flag.get();
}
}
The client does exactly that: It opens a connection, and nothing else
import java.io.IOException;
import java.net.Socket;
public class RemoteExitClient
{
public static void main(String[] args)
{
Socket socket = null;
try
{
socket = new Socket("localhost", 1234);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (socket != null)
{
try
{
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
The application is then also very simple:
public class RemoteExitTest
{
public static void main(String[] args)
{
RemoteExitServer e = new RemoteExitServer();
while (!e.shouldExit())
{
System.out.println("Working...");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
System.out.println("done");
}
}
(The code could be made even more concise with try-with-resources, but this should not matter here)