I have the following RMI server code:
public class ServerProgram {
public ServerProgram() {
try {
LocateRegistry.createRegistry(1097);
Calculator c = new CalculatorImpl();
String name = "rmi://host:port/name";
Naming.rebind(name, c);
System.out.println("Service is bound......");
} catch (Exception e) {
}
}
public static void main(String[] args) {
new ServerProgram();
}
}
When the above program running, it keeps running to wait for client requests. But what I do not understand is what make that program keeps running while it is not in something like while(true){}; and how to stop it from listening, except stopping the whole program?
What makes it keep running is a non-daemon listening thread started by RMI. To make it exit, unbind the name and unexport both the Registry and the remote object, with UnicastRemoteObject.unexportObject().
To stop it, you should call
LocateRegistry.getRegistry().unbind("rmi://host:port/name");
But what I do not understand is what make that program keeps running while it is not in something like while(true){}; and how to stop it from listening, except stopping the whole program?
This is done by a edit non-editdaemon thread. See: What is Daemon thread in Java?
You can test the behavior with this little example:
public class DaemonThread extends Thread
{
public void run(){
System.out.println("Entering run method");
try
{
System.out.println(Thread.currentThread());
while (true)
{
try {Thread.sleep(500);}
catch (InterruptedException x) {}
System.out.println("Woke up");
}
}
finally { System.out.println("run finished");}
}
public static void main(String[] args) throws InterruptedException{
System.out.println("Main");
DaemonThread t = new DaemonThread();
t.setDaemon(false); // Set to true for testing
t.start();
Thread.sleep(2000);
System.out.println("Finished");
}
}
The setting prevents the JVM to shut down. after System.out.println("Finished"); you still see the thread running with it's "Woke up" log outputs.
Related
I was tasked to write a small server application. It is supposed to be started via the console and then run in the background, processing some network traffic and calculating stuff locally until it receives a shutdown signal. I am pretty sure i can handle all of that - except the very basic application architecture. I am super unsure how to bring my main loop to wait for the application to finish. So here is my current code, cleaned up and omitting unnecessary parts.
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 looks like this:
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;
}
Now for the actual question: is there a more elegant or more efficient way to go about this? i am talking about this part specifically:
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);
}
Is thread.sleep okay here? Could or should i even omit it? I want to wait here at this very point of my code, so i can clean up after execution stops.
You can make your server something runnable, pack that into a Thread and join!
Example
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("Starting Server!");
t.start();
t.join();
System.out.println("Server is done!");
}
Also you can use CountDownLatch for your purpose, see example:
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");
}
}
Also with CountDownLatch you can create multiple server instances and waiting them in main thread until they are all done.
It depends on how you're managing your threads.
At the lowest level Java thread API, your main thread can wait for the server thread to complete with:
serverThread.join();
Look at the Thread API for more options, such as putting a timeout on the join() (so you can take increasingly drastic measures to make it end).
Higher level threading abstractions such as Executor, Future, ForkJoinTask etc. give you the same ability with different APIs. A thorough exploration of these is beyond the scope of a SO answer -- Oracle has tutorials on concurrency, or there are books.
I'm writing a program that listens to clipboard changes and print that changes to stdout (it's just a test for a bigger program). The problem is: when the main thread finishes, the JVM exits and no events arrive to the listener. How can I do to keep JVM running while listening the clipboard?
My code looks like this:
public class Test {
public static void main(String[] args) {
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
cb.addFlavorListener(new FlavorListener() {
#Override
public void flavorsChanged(FlavorEvent e) {
System.out.println(e);
}
});
}
}
Thanks!
How can I do to keep JVM running while listening the clipboard?
I can't see how you would tell the program to stop listening to the clipboard in a proper way.
What I would do is just print some kind of message using standard out indicating a key to exit the program and then calling a scanner or similiar for checking the input. This way you achieve 2 important points:
The thread doesn't die inmediately as the scanner does the "wait" part I think you are looking for.
Users get control over the thread's lifecycle, so they can terminate it whenever they want in a proper way
I would just let the main-Thread sleep:
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.FlavorEvent;
import java.awt.datatransfer.FlavorListener;
public class Test {
public static void main(String[] args) throws InterruptedException {
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
cb.addFlavorListener(new FlavorListener() {
#Override
public void flavorsChanged(FlavorEvent e) {
System.out.println(e);
}
});
// sleep forever
Object o = new Object();
synchronized (o) {
o.wait();
}
}
}
It is important to keep at least one (non-deamon) thread alive, to keep your application running. An alive thread could be:
The main thread, put to sleep
A new thread, put to sleep
Any awt/swing application thread, that will usualy stay alive, as long as there is at least one element undisposed
Any other thread, listening to any interface (waiting for System.in, HTTP-Request, or just anything)
Concerning the sleep mechanism, here are my three different techiques:
Never do this, it will keep your CPU busy:
for(;;);
This code's intention is clearly visible:
for(;;) Thread.sleep(Long.MAX_VALUE);
More elegant:
Object o = new Object();
synchronized (o) {o.wait();}
See How do you hang a thread in Java in one line? for a discussion about sleeping.
Try this:
public static void listen() throws InterruptedException {
Thread t = new Thread (new Runnable(){
#Override
public void run() {
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable contents = cb.getContents(null);
cb.addFlavorListener(new FlavorListener() {
#Override
public void flavorsChanged(FlavorEvent e) {
try {
System.out.println("Got Data:"+(String)contents.getTransferData(DataFlavor.stringFlavor));
} catch (UnsupportedFlavorException | IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
}
});
t.setDaemon(true);
t.start();
while (true)
Thread.sleep(Long.MAX_VALUE);
}
I have some problem with java.
for Example,
public class Test implements Runnable{
Thread thread;
public Test() throws Exception{
thread = new Thread(this);
thread.setName(getClass().getName() + thread.getId());
thread.start();
}
public void run() {
System.out.println("start");
try {
while(!thread.isInterrupted())
Thread.sleep(Long.MAX_VALUE);
}
catch(InterruptedException ie) {
System.out.println("interrupted");
}
System.out.println("stop");
}
public void stop() {
thread.interrupt();
}
}
this code now is infinite sleep status.
then, I find this thread by name in another Java code (something like this way - http://www.ehow.com/how_7467934_java-thread-runtime.html)
I casted "found thread" to Test class
Test test = (Test)Found Thread;
finally,
test.stop();
work!
I want to find and stop this thread in the other application (absolutely not same)
I`m not familiar with Java, also this like code way will not work in C++ or others as I know.
Is my code in sense? no problem? I worry about...
please advise me. thanx a lot.
(I`m not good at english. sorry)
There is no problem in your code! Everything is just perfect. You may omit checking interrupted status of thread in sleep loop, because once thread is interrupted, it will going to throw that exception when it tries to sleep or wait.
public class Test implements Runnable {
Thread thread;
public Test() throws Exception {
thread = new Thread(this);
thread.setName(getClass().getName() + thread.getId());
thread.start();
}
public void run() {
System.out.println("start");
try {
while (true) {
Thread.sleep(Long.MAX_VALUE);
}
} catch (InterruptedException ie) {
System.out.println("interrupted");
}
System.out.println("stop");
}
public void stop() {
thread.interrupt();
}
public static void main(String [] args) throws Exception{
Test t = new Test();
t.stop();
}
}
I have a class which encapsulates a Server Socket i.e. a server functionality.
The interface of the class is:
class Server{
public void start();
public void stop();
}
the start is as follows:
public void start(){
ExecutorService tp = Executors.newSingleThreadExecutor();
while(!stop){
try {
Socket clientConnection = serverSocket.accept();
tp.execute(new ClientProcessor(clientConnection));
} catch (IOException e) {
stop = true;
}
}
I have trouble figuring out how I would start this without blocing my main.
I mean I need to start the server from a background thread so I thought of the following:
ExecutorService tp2 = Executors.newSingleThreadExecutor();
tp.submit(new Runnable(){
public void run(){
Server s = new Server();
s.start();
}
});
}
But what I want is to know that the server started and did not throw an exception. How can I do that?
I.e. how can I know from my main thread that the background server started fine and so I can continue with the rest actions?
Start the server.
Wait a bit.
Try to connect to it on the local stack. If the connect succeeds, you have a winner - just close the temp connection.
Here is a very simple example (though there are many better - and more complicated - ways):
interface Server implements Thread{
public void startup();
public void shutdown();
}
class MyServer implements Server{
private Exception serverError=null;
ExecutorService singleThreadManager;
public Exception getServerError(){
return serverError;
}
public void run(){
while(!stop){
try {
Socket clientConnection = serverSocket.accept();
singleThreadManager.execute(new ClientProcessor(clientConnection));
} catch (IOException e) {
serverError = e;
// stop = true;
shutdown(); // shutdown cleanly after exception
}
}
}
public void startup(){
singleThreadManager = Executors.newSingleThreadExecutor();
// do setup tasks and then
start(); // thread.run() will now be called asynchronously
}
}
public static void main (String ... args){
MyServer s = new MyServer();
s.startup();
// whenever you want you can now call
Exception x = s.getServerError();
// to see whether the server has shutdown because of an error.
}
maybe you can implement an Event Handler into your main application. Your main application should be registered as eventlistener to your server class.
Please have a look at the following link, it shows you an example of event handling for C# and the same example for Java
http://scatteredcode.wordpress.com/2011/11/24/from-c-to-java-events/
A simple way of doing this would be to collect all exceptions in a collection and return them to the foreground thread at some point in time.
class Server{
private Collection<? extends Exception> exceptions = new ArrayList<Exception>();
public void start()
{
try{ /* do something*/ }
catch(Exception e)
{
exceptions.add(e)
}
}
public void stop();
public Collection<Exception> getAllExceptions()
{
return exceptions;
}
public boolean checkOk()
{
return 0 == exceptions.size();
}
}
Elaboration on how to transfer data between threads:
If you declared your server similarly to my suggestion above, then we can change the code you have used to spawn your server to transfer the serverStartupOk information:
ExecutorService tp2 = Executors.newSingleThreadExecutor();
final boolean[] result = new boolean[1]; //Final object so it can pass between threads
tp.submit(new Runnable(){
public void run(){
Server s = new Server();
s.start();
result[0] = s.checkOk(); // Retrieve the check from the server, store it in
// final array variable
}
});
boolean serverStartupOk = result[0];
System.out.println("Server startup succesful: " + Boolean(serverStartupOk).toString());
}
Use your own ThreadPoolExecutor instead of the pre-baked ones in Executors. Then override the afterExecute hook provided by TPE to do whatever you want with the exceptions.
I'm reading a bit between the lines here, but it looks like you want to know if the initial listen on the socket succeeded or not. If you wanted to wait and see if any client failed, then there would be no need to run it in a different thread.
If that's correct, then you can catch any exceptions emitted by the initial TCP server socket instantiation before you start the thread to handle client connections. Pass the server in to the new thread, instead of creating it in the new thread.
I have developed an application which is intended to allow users to execute queries.Once the user enters the query and clicks on execute button the control is passed to RMI server which in turn starts the thread.
User should be able to execute other quesries one after the other and each query will b executed in different thread.
I am not able to stop the execution of the thread. I want to stop the execution while it is executing or on the button click event based on the thread id passed.
I am trying below code
public class AcQueryExecutor implements Runnable {
private volatile boolean paused = false;
private volatile boolean finished = false;
String request_id="",usrnamee="",pswd="",driver="",url="";
public AcQueryExecutor(String request_id,String usrnamee,String pswd,String driver,String url) {
this.request_id=request_id;
this.usrnamee=usrnamee;
this.pswd=pswd;
this.url=url;
this.driver=driver;
}
public void upload() throws InterruptedException {
//some code
stop();
//some more code
}
public void run() {
try {
while(!finished) {
upload();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void stop() {
finished = true;
}
}
RMI server class from where I start the thread
public class ExecutorServer extends UnicastRemoteObject implements ExecutorInterface
{
public ExecutorServer()throws RemoteException
{
System.out.println("Server is in listening mode");
}
public void executeJob(String req_id,String usrname,String pwd,String driver,String url)throws RemoteException
{
try{
System.out.println("Inside executeJob.wew..");
AcQueryExecutor a=new AcQueryExecutor(req_id,usrname,pwd,driver,url);
Thread t1 = new Thread(a);
t1.start();
}
catch(Exception e)
{
System.out.println("Exception " + e);
}
}
public void killJob(String req_id)throws RemoteException{
logger.debug("Kill task");
AcQueryExecutor a=new AcQueryExecutor(req_id,"","","","");
a.stop();
}
public static void main(String arg[])
{
try{
LocateRegistry.createRegistry(2007);
ExecutorServer p=new ExecutorServer();
Naming.rebind("//localhost:2007/exec1",p);
System.out.println ("Server is connected and ready for operation.");
}catch(Exception e)
{
System.out.println("Exception occurred : "+e.getMessage());
e.printStackTrace();
}
}
}
RMI client
ExecutorInterface p=(ExecutorInterface)Naming.lookup("//localhost:2007/exec1");
System.out.println("Inside client.."+ p.toString());
p.executeJob(id, usrname, pswd);
p.killJob(id);
}
Till my knowlegde p.killJob() will wont be invoked untill executeJob() is finished.
I want to stop the execution while it is running
The problem appears to be that you are allocating a fresh instance of the Runnable AcQueryExecutor for each thread. This means each is seeing its own finished flag. Setting one in killJob will not lead to any other thread exiting because no other thread shares this flag.
You'll need to share Runnables or else make the finish field static. The latter will cause all threads to exit whenever any instance's stop is called, so may not be what you want.