I'm following Jenkov's tutorial on vertx. Here I have two files:
MyVerticle.java:
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
public class MyVerticle extends AbstractVerticle {
#Override
public void start(Future<Void> startFuture) {
System.out.println("MyVerticle started!");
}
#Override
public void stop(Future stopFuture) throws Exception {
System.out.println("MyVerticle stopped!");
}
}
and VertxVerticleMain.java:
import io.vertx.core.Vertx;
public class VertxVerticleMain {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new MyVerticle());
}
}
After running VertxVerticleMain.java, I saw "MyVerticle started!" in Eclipse's console but don't know how to call stop in MyVerticle.
Jenkov said that The stop() method is called when Vert.x shuts down and your verticle needs to stop. How exactly do I shut down my Vert.x and stop this verticle? I want to see MyVerticle stopped! in the console.
From the Vert.x docs:
Vert.x calls this method when un-deploying the instance. You do not call it yourself.
If you run Vert.x from a main method and you terminate the JVM process (by clicking the 'stop' button in Eclipse, for example), Vert.x probably isn't signaled to undeploy the verticles, or the JVM terminates before Vert.x has time to undeploy the verticles.
You can do a number of things to ensure that the verticle will be undeployed and the stop() method will be called:
Start the Verticle using the vertx commandline. When you stop the process (or tell vert.x to stop), Vert.x will make sure that all verticles are undeployed.
You can programmatically undeploy the deployed verticles by fetching the list of deploymentId's and calling undeploy for all id's:
vertx.deploymentIDs().forEach(vertx::undeploy);
You can programmatically tell Vert.x to stop:
vertx.close();
You can add a shutdown hook to make sure that one of the options above is executed on JVM termination:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
vertx.close();
}
});
You can either programmatically undeploy the verticle by calling the Vert.x API, or just stop the Java process, which in term triggers the Vert.x process to stop.
By the way, it's worth asking yourself whether it's really necessary that the stop() method is always called when the process running the verticle stops. You can never be sure that that happens; when the process is forced to stop or killed, the stop() method might not be called.
your code should add super.stop() and super.start() function like that:
public class MyVerticle extends AbstractVerticle {
#Override
public void start(Future<Void> startFuture) {
//must call super.start() or call startFuture.complete()
super.start(startFuture);
System.out.println("MyVerticle started!");
System.out.println("Verticle_stopFuture.start(): deployId=" + context.deploymentID());
}
#Override
public void stop(Future stopFuture) throws Exception {
//must call super.stop() or call stopFuture.complete()
super.stop(stopFuture);
System.out.println("MyVerticle stopped!");
}
}
and VertxVerticleMain.java:
public class VertxVerticleMain {
static String verticle_deployId;
public static void main(String[] args) throws InterruptedException {
System.out.println("start main(): thread="+Thread.currentThread().getId());
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new MyVerticle(), new Handler<AsyncResult<String>>(){
#Override
public void handle(AsyncResult<String> asyncResult) {
if (asyncResult.succeeded()) { // khi startFuture.complete() đc gọi
System.out.println("asyncResult = DeployId =" + asyncResult.result());
verticle_deployId = asyncResult.result();
} else { //khi startFuture.fail() đc gọi
System.out.println("Deployment failed!"); //vì chưa đc cấp id
}
}
});
// waiting for Verticle context is allocate by Vertx
Thread.currentThread().sleep(500);
Set<String> deploymentIDs = vertx.deploymentIDs();
System.out.println("============== (sleeped 500ms wait for Context allocated), list of deploymentIDs: number Deployments =" + deploymentIDs.size());
for(String depId: deploymentIDs){
//
System.out.println(depId);
}
//close verticle here
vertx.undeploy(verticle_deployId);
}
}
Related
I need to create a RMI service which can notify events to clients.
Each client register itself on the server, the client can emit an event and the server will broadcast it to all other clients.
The program works, but, the client reference on the server is never garbage collected, an the thread which the server uses to check if the client reference will never terminate.
So each time a client connects to the server, a new thread is created and never terminated.
The Notifier class can register and unregister a listener.
The broadcast method call each registered listener and send the message back.
public class Notifier extends UnicastRemoteObject implements INotifier{
private List<IListener> listeners = Collections.synchronizedList(new ArrayList());
public Notifier() throws RemoteException {
super();
}
#Override
public void register(IListener listener) throws RemoteException{
listeners.add(listener);
}
#Override
public void unregister(IListener listener) throws RemoteException{
boolean remove = listeners.remove(listener);
if(remove) {
System.out.println(listener+" removed");
} else {
System.out.println(listener+" NOT removed");
}
}
#Override
public void broadcast(String msg) throws RemoteException {
for (IListener listener : listeners) {
try {
listener.onMessage(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
The listener is just printing each received message.
public class ListenerImpl extends UnicastRemoteObject implements IListener {
public ListenerImpl() throws RemoteException {
super();
}
#Override
public void onMessage(String msg) throws RemoteException{
System.out.println("Received: "+msg);
}
}
The RunListener client subscribes a listener wait few seconds to receive a message and then terminates.
public class RunListener {
public static void main(String[] args) throws Exception {
Registry registry = LocateRegistry.getRegistry();
INotifier notifier = (INotifier) registry.lookup("Notifier");
ListenerImpl listener = new ListenerImpl();
notifier.register(listener);
Thread.sleep(6000);
notifier.unregister(listener);
UnicastRemoteObject.unexportObject(listener, true);
}
}
The RunNotifier just publish the service and periodically sends a message.
public class RunNotifier {
static AtomicInteger counter = new AtomicInteger();
public static void main(String[] args) throws RemoteException, AlreadyBoundException, NotBoundException {
Registry registry = LocateRegistry.createRegistry(1099);
INotifier notifier = new Notifier();
registry.bind("Notifier", notifier);
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
try {
int n = counter.incrementAndGet();
System.out.println("Broadcasting "+n);
notifier.broadcast("Hello ("+n+ ")");
} catch (RemoteException e) {
e.printStackTrace();
}
}
},5 , 5, TimeUnit.SECONDS);
try {
System.in.read();
} catch (IOException e) {
}
executor.shutdown();
registry.unbind("Notifier");
UnicastRemoteObject.unexportObject(notifier, true);
}
}
I've seen many Q&A on stack overflow about RMI, but none addresses this kind of problem.
I guess I'm doing some very big mistake, but I can't spot it.
As you can see in the picture, a new RMI RenewClean thread is created for each incoming connection, and this thread will never terminate.
Once the client disconnects, and terminates, the RenewClean thread will silently swallow all ConnectionException thrown and will keep polling a client which will never reply.
As a side note, I even tried to keep just weak reference of the IListener in the Notifier class, and still the results are the same.
This may not be very helpful if you are stuck on JDK1.8, but when I test on JDK17 the multiple rmi server threads created for each incoming client RMI RenewClean-[IPADDRESS:PORT] are cleaned up on the server, and not showing "will never terminate" behaviour you may have observed on JDK1.8. It may be a JDK1.8 issue, or simply that you are not waiting long enough for the threads to end.
For quicker cleanup, try adjusting the system property for client thread garbage collection setting from the default (3600000 = 1 hour):
java -Dsun.rmi.dgc.client.gcInterval=3600000 ...
On my server I added this in one of the API callbacks:
Function<Thread,String> toString = t -> t.getName()+(t.isDaemon() ? " DAEMON" :"");
Set<Thread> threads = Thread.getAllStackTraces().keySet();
System.out.println("-".repeat(40)+" Threads x "+threads.size());
threads.stream().map(toString).forEach(System.out::println);
After RMI server startup it printed names of threads and no instances of "RMI RenewClean":
---------------------------------------- Threads x 12
After connecting many times from a client, the server reported corresponding instances of "RMI RenewClean":
---------------------------------------- Threads x 81
Leaving the RMI server for a while, these gradually shrank back - not to 12 threads -, but low enough to suggest that RMI thread handling is not filling up with many unnecessary daemon threads:
---------------------------------------- Threads x 20
After about an hour all the remaining "RMI RenewClean" were removed - probably due to housekeeping performed at the interval defined by the VM setting sun.rmi.dgc.client.gcInterval=3600000:
---------------------------------------- Threads x 13
Note also that RMI server shutdown is instant at any point - the "RMI RenewClean" daemon threads do not hold up rmi server shutdown.
I am trying to set up a shutdown hook to handle SIGTERM (kill -15). It shuts down but doesn't look like it gracefully finish up ** processing** function as it never output the log "Thread has been shutdown".
public class Runner {
public static void main(String[] args) {
Test test = new Test();
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
logger.warn("Shutting things down..."); // This works
test.stop();
} catch (Exception ex) {
logger.error("Error shutting the app gracefully", ex);
}
}
});
test.processing();
}
}
public class Test {
private volatile boolean processingExit = false;
public void stop() {
processingExit = true;
}
public void processing() {
while (!processingExit) {
//do work here
logger.info("doing work... keep printing..."); //This works until I send a kill -15 signal
}
// This log never works
logger.info("Thread has been shutdown"); // This doesn't works
}
}
The problem is that as soon as the shutdown hook thread completes, the process is halted, you need to have the shutdown hook thread wait for the main thread.
Copied from https://stackoverflow.com/a/2922031/1544715
From the docs:
When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. When all the hooks have finished it will then run all uninvoked finalizers if finalization-on-exit has been enabled. Finally, the virtual machine will halt.
I have a GUI program that executes TestNG automation scripts. It's meant for users to easily configure some setting and launch the automation script that they want.
One thing I need to add is the ability to instantly stop the running TestNG process. Something like how in Eclipse, the 'Terminate' button will instantly stop whatever is running.
This is what the code that launches the TestNG tests looks like:
public class ScriptRunner implements Runnable {
public void runScript() {
Thread testRun = new Thread(this);
testRun.start();
}
#Override
public void run() {
//various other things are configured for this,
//but they're not relevant so I left them out
TestNG tng = new TestNG();
//While this runs, various browser windows are open,
//and it could take several minutes for it all to finish
tng.run();
}
}
As per the comment, the tng.run() can take several minutes to complete, and it's performing several things, opening/closing browser windows, etc.
How can I just instantly terminate the process, like you would when running an application from an IDE?
EDIT:
Per the comments, I'm attempting to use a ServiceExecutor and shutDownNow() The code is looking like this:
ExecutorService executorService = Executors.newFixedThreadPool(10);
public void runScript() {
executorService.execute(this);
}
//this method gets called when I click the "stop" button
public void stopRun() {
executorService.shutdownNow();
}
#Override
public void run() {
//same stuff as from earlier code
}
Spawn a child JVM process using ProcessBuilder or Runtime and you will be able to terminate that process when the user requests that the script stops running.
You can use ExecutorService to start test execution into one another thread. You can choose to have many thread in parrallel or juste one thread for all tests in sequence by choosing which executor service you need.
After that, start the execution of all tests in the same executor service instance by calling submit() method on it. You can stop the execution of all submitted runnables by calling shutdownNow() method.
It is important to use the same instance of ExecutorService, otherwise you start each test in a different thread and you will not enable to break the execution chain (or by calling shutdownNow() on all of them).
I was recently working on the executor framework. Here I have listed my problem
http://programtalk.com/java/executorservice-not-shutting-down/
Be careful if you are doing some IO operations the executor service may not shutdown immediately. If you see the below code stopThread is important because it tells your program that the thread has been asked to stop. And you can stop some iteration what you are doing.
I will modify your code like this:
public class MyClass {
private ExecutorService executorService;
private boolean stopThread = false;
public void start() {
// gives name to threads
BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("thread-%d").build();
executorService = Executors.newSingleThreadExecutor(factory);
executorService.execute(new Runnable() {
#Override
public void run() {
try {
doTask();
} catch (Exception e) {
logger.error("indexing failed", e);
}
}
});
executorService.shutdown();
}
private void doTask() {
logger.info("start reindexing of my objects");
List<MyObjects> listOfMyObjects = new MyClass().getMyObjects();
for (MyObjects myObject : listOfMyObjects) {
if(stopThread){ // this is important to stop further indexing
return;
}
DbObject dbObjects = getDataFromDB();
// do some task
}
}
public void stop() {
this.stopThread = true;
if(executorService != null){
try {
// wait 1 second for closing all threads
executorService.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
What about this,
add a volatile static boolean and make the thread code look like...
if(ScriptRunner.runThread){
//Do some stuff here
}
if(ScriptRunner.runThread){
//Do some other stuff here
}
if(ScriptRunner.runThread){
//Do some other stuff here
}
if(ScriptRunner.runThread){
//Do rest of the stuff here
}
Now you can add a button in your main GUI that simply sets the runThread to false so the thread will terminate nearly instant leaving all the leftover code untouched as you press the Stop button.
public class ScriptRunner implements Runnable {
volatile static Boolean runThread = true;
public void runScript() {
Thread testRun = new Thread(this);
testRun.start();
}
public void terminate(){
runThread = false;
}
#Override
public void run() {
//various other things are configured for this,
//but they're not relevant so I left them out
TestNG tng = new TestNG();
//While this runs, various browser windows are open,
//and it could take several minutes for it all to finish
tng.run();
}
}
How about a new Thread? You have to add an private Thread thread; in the gui and when ever you start
thread = new thread(){
#Override
public void run(){
//start process here
}
};
thread.start();
and to stop "terminate"
thread.stop();(depracted) or thread.setDeamon(true);
Everytime I have to stop a process by the gui I use this.
Hope I could help ;)
In your GUI somewhere you have something like
ScriptRunner scriptRunner = new ScriptRunner();
scriptRunner.runScript();
When you want to stop it call
scriptRunner.interrupt();
Change the code in ScriptRunner
private Thread testRun;
public void runScript() {
testRun = new Thread(this);
testRun.start();
}
public void interrupt() {
testRun.interrupt();
}
Save all created processes and kill them when your program ends:
public class ProcessFactory {
private static Set<Process> processes = new HashSet<>();
private static boolean isRunning = true;
public static synchronized Process createProcess(...) throws ... {
if (!isRunning)
throw ...
... // create your spawned process
processes.add(process);
return process;
}
public static synchronized void killAll() {
isRunning = false;
for (Process p : processes)
p.destroy();
processes.clear();
}
public static void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
void run() {
killAll();
}
});
}
}
This can be improved by adding a mechanism that removes already dead processes, but you get the general idea.
In C programs using system threads for example, I can pass a SIGINT with Ctrl+C and the process will be killed silently. But when I do the same thing to a Java program with threads, locks, semaphores et cetera, the JVM just stops there and I have to kill the process "outside", by closing the terminal or rebooting the system. How can a make a Java program silently exit as it should without closing the terminal when I see some wrong behaviors in runtime?
You can add a shutdown hook to the JVM that gets triggered when a SIGINT is received and then in there call Runtime.getRuntime().halt(0). That will kill the process. You can even use the Shutdown Hook to clean your running Threads.
[EDIT] My initial answer was to use System.exit() in the hook. But that will not work because System.exit will trigger the already running hook.
You can try this example with the hook and not registering the hook.
public class Exit {
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new ExitHok());
Thread t = new Thread(new Printer());
t.start();
}
private static class ExitHok extends Thread {
#Override
public void run() {
System.out.println("Received shutdown");
Runtime.getRuntime().halt(0);
}
}
private static class Printer implements Runnable {
#Override
public void run() {
int counter = 0;
while (true) {
System.out.println(++counter);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
}
In .NET, you can check the Environment.HasShutdownStarted property to see whether your service is being unloaded for whatever reason, and perform graceful unloading/cleanup.
So instead of:
while (true) { }
...you can use...
while (!Environment.HasShutdownStarted) { }
Is there an equivalent thing in Java?
Perhaps you're looking for a shutdown hook? This allows you to specify a thread to be run when the application is closed (as long as it's not brutally forced closed with kill -9 or similar, but in that case no environment can guarantee to do anything on shutdown.)
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
//Code here.
}
});
From a practical perspective, you should also make these threads quick to execute - since otherwise the application will appear to hang upon exiting, and no-one likes that (plus, the OS or user may choose to kill off the application, aborting the hook at an arbitrary point.)
You can add multiple shutdown hooks, and they will be executed concurrently (and in an arbitrary order.)
Removal of shutdown hooks can be down in a similar way by calling removeShutdownHook().
You could add a shutdown hook. Basically registers an unstarted thread that will run when the application terminates.
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
// logic for making a clean shutdown...
}
})
The link above has a very good description of what happens during shutdown.
You can look at the shutdown hook API, and instead of doing
while(true) {
}
You can declare a member in your thread/runnable implementation to signify shutdown:
class MyRunnable implements Runnable {
private running= false;
public void setRunning(boolean running) {
running= running;
}
public void run() {
setRunning(true);
while(running) {
// do task
}
}
}
public static void main(String[] args) {
final MyRunnable myRunnable= new MyRunnable();
final Thread runThread= new Thread(myRunnable);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
myRunnable.setRunning(false);
}
});
runThread.start();
runThread.join();
}
This is not a perfect solution, but should get you at least in the right direction.