The following daemon-bean is running:
public class DaemonBean extends Thread {
private final static Logger log = LoggerFactory.getLogger(DaemonBean.class);
{
setDaemon(true);
start();
}
#Override
public void run() {
for(int i=0; i<10 && !isInterrupted(); ++i) {
log.info("Hearbeat {}", i);
try {
sleep(1000);
} catch (InterruptedException e) {
return;
}
}
}
}
It is daemon, so would terminate if singleton.
So, the following non-daemon bean is waiting for him:
public class Waitor1 extends Thread {
private final static Logger log = LoggerFactory.getLogger(Waitor1.class);
private Thread joinable;
{
setDaemon(false);
setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
log.error("Error in thread", e);
}
});
}
public Thread getJoinable() {
return joinable;
}
public void setJoinable(Thread value) {
this.joinable = value;
if( this.joinable != null ) {
start();
}
}
#Override
public void run() {
log.info("Waiting started");
try {
joinable.join();
} catch (InterruptedException e) {
log.info("Thread interrupted");
return;
}
log.info("Waiting ended");
}
}
The Spring configuration for beans is:
<bean id="daemon" class="beans.DaemonBean"/>
<bean id="waitor" class="beans.Waitor1">
<property name="joinable" ref="daemon"/>
</bean>
The question is: why is it working if runned from main and not working if ran from jUnit test?
Running code is
public static void main(String[] args) {
new ClassPathXmlApplicationContext("/beans/Waiting1.xml");
}
or
#Test
public void testWaiting1() {
new ClassPathXmlApplicationContext("/beans/Waiting1.xml");
}
In case of main I see all hearbeats. In case of jUnit I see only heartbeat 0, then message "Waiting started" and the program is terminated as if nobody waiting for non-daemon threads here.
What can be the reason of it?
When you run your code from main it creates both beans, thus two threads - daemon and non-daemon. As long as non-daemon thread is running, your application won't exit. So it works.
It's different when run from JUnit. As soon as JUnit test method completes (and it completes immediately after the Spring context is up), JUnit assumes your tests are done. Thus it kills all your threads and basically the whole JVM.
Remember your Waitor1 bean spawns a background thread which JUnit doesn't care about. As soon as you leave #Test method JUnit will just stop everything.
Related
I'm using a few services inheriting from the AbstractScheduledService, which get managed by a ServiceManager. Everything works fine, but now, there's a service whose runOneIteration takes a rather long time, and as the result, my process takes too long to terminate (more than five seconds).
There are other services inheriting from AbstractExecutionThreadService, which had a similar problem, which I could solve via
#Override
protected final void triggerShutdown() {
if (thread != null) thread.interrupt();
}
and storing private volatile thread in the run method. However, there's no triggerShutdown for AbstractScheduledService as stated in this issue.
I already considered alternatives like making runOneIteration do less work, but it's both ugly and inefficient.
I can't override stopAsync as it's final and I can't see anything else. Is there a hook for doing something like this?
Can you work with this? Was there any reason you couldn't add a triggerShutdown yourself?
class GuavaServer {
public static void main(String[] args) throws InterruptedException {
GuavaServer gs = new GuavaServer();
Set<ForceStoppableScheduledService> services = new HashSet<>();
ForceStoppableScheduledService ts = gs.new ForceStoppableScheduledService();
services.add(ts);
ServiceManager manager = new ServiceManager(services);
manager.addListener(new Listener() {
public void stopped() {
System.out.println("Stopped");
}
public void healthy() {
System.out.println("Health");
}
public void failure(Service service) {
System.out.println("Failure");
System.exit(1);
}
}, MoreExecutors.directExecutor());
manager.startAsync(); // start all the services asynchronously
Thread.sleep(3000);
manager.stopAsync();
//maybe make a manager.StopNOW()?
for (ForceStoppableScheduledService service : services) {
service.triggerShutdown();
}
}
public class ForceStoppableScheduledService extends AbstractScheduledService {
Thread thread;
#Override
protected void runOneIteration() throws Exception {
thread = Thread.currentThread();
try {
System.out.println("Working");
Thread.sleep(10000);
} catch (InterruptedException e) {// can your long process throw InterruptedException?
System.out.println("Thread was interrupted, Failed to complete operation");
} finally {
thread = null;
}
System.out.println("Done");
}
#Override
protected Scheduler scheduler() {
return Scheduler.newFixedRateSchedule(0, 1, TimeUnit.SECONDS);
}
protected void triggerShutdown() {
if (thread != null) thread.interrupt();
}
}
}
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.
In the Java tutorial it says about try { ... } finally { ... }:
Note: If the JVM exits while the try or catch code is being executed,
then the finally block may not execute. Likewise, if the thread
executing the try or catch code is interrupted or killed, the finally
block may not execute even though the application as a whole
continues.
Is it true that a thread can be interrupted or killed (I thought that was impossible?) such that the finally block will not be executed while the JVM running this thread is not exited/killed? (I am puzzled because the quote above is pretty explicit about this, not much room for misunderstanding.)
Edit: Broke the question down to its core intend.
Well, I stand corrected. It is possible by using deprecated methods:
#Test
public void testThread() throws Exception {
Thread thread = new Thread(new MyRunnable());
thread.start();
Thread.sleep(100);
thread.suspend();
Thread.sleep(2000);
}
class MyRunnable implements Runnable {
#Override
public void run() {
System.out.println("Start");
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("Done");
}
}
}
Due to the pausing which will (most likely) occure while the thread is asleep, the finally block will never be executed.
Rafael, I believe this is one of the edge cases you are after. If a thread is blocked on something native (eg reading from STDIN or a Socket), and the JVM is in a state of shutdown, and the thread is interrupted, then finally may not be invoked.
The following example indicates this without invoking deprecated methods:
Sleep - finally is invoked.
SystemIn - finally is not invoked.
The example is very contrived, and is purely provided for demonstrative purposes :)
public class Interrupted {
static final List<Thread> THREADS = Arrays.asList(
new Thread(new Sleep()),
new Thread(new SystemIn())
);
static final CountDownLatch LATCH = new CountDownLatch(THREADS.size());
public static void main(String[] args) throws Exception {
Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownHook()));
for (Thread thread : THREADS) {
thread.start();
}
System.out.println("[main] Waiting for threads to start...");
LATCH.await();
System.out.println("[main] All started, time to exit");
System.exit(0);
}
static abstract class BlockingTask implements Runnable {
#Override
public void run() {
final String name = getClass().getSimpleName();
try {
LATCH.countDown();
System.out.printf("[%s] is about to block...%n",name);
blockingTask();
} catch (Throwable e) {
System.out.printf("[%s] ", name);
e.printStackTrace(System.out);
} finally {
System.out.printf("[%s] finally%n", name);
}
}
abstract void blockingTask() throws Throwable;
}
static class Sleep extends BlockingTask {
#Override
void blockingTask() throws Throwable {
Thread.sleep(60 * 60 * 1000); // 1 hour
}
}
static class SystemIn extends BlockingTask {
#Override
void blockingTask() throws Throwable {
System.in.read();
}
}
static class ShutdownHook implements Runnable {
#Override
public void run() {
System.out.println("[shutdown-hook] About to interrupt blocking tasks...");
for (Thread thread : THREADS) {
thread.interrupt();
}
System.out.println("[shutdown-hook] Interrupted");
try {
for (int i=0; i<10; i++) {
Thread.sleep(50L);
System.out.println("[shutdown-hook] Still exiting...");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
The following daemon-bean is running:
public class DaemonBean extends Thread {
private final static Logger log = LoggerFactory.getLogger(DaemonBean.class);
{
setDaemon(true);
start();
}
#Override
public void run() {
for(int i=0; i<10 && !isInterrupted(); ++i) {
log.info("Hearbeat {}", i);
try {
sleep(1000);
} catch (InterruptedException e) {
return;
}
}
}
}
It is daemon, so would terminate if singleton.
So, the following non-daemon bean is waiting for him:
public class Waitor1 extends Thread {
private final static Logger log = LoggerFactory.getLogger(Waitor1.class);
private Thread joinable;
{
setDaemon(false);
setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
log.error("Error in thread", e);
}
});
}
public Thread getJoinable() {
return joinable;
}
public void setJoinable(Thread value) {
this.joinable = value;
if( this.joinable != null ) {
start();
}
}
#Override
public void run() {
log.info("Waiting started");
try {
joinable.join();
} catch (InterruptedException e) {
log.info("Thread interrupted");
return;
}
log.info("Waiting ended");
}
}
The Spring configuration for beans is:
<bean id="daemon" class="beans.DaemonBean"/>
<bean id="waitor" class="beans.Waitor1">
<property name="joinable" ref="daemon"/>
</bean>
The question is: why is it working if runned from main and not working if ran from jUnit test?
Running code is
public static void main(String[] args) {
new ClassPathXmlApplicationContext("/beans/Waiting1.xml");
}
or
#Test
public void testWaiting1() {
new ClassPathXmlApplicationContext("/beans/Waiting1.xml");
}
In case of main I see all hearbeats. In case of jUnit I see only heartbeat 0, then message "Waiting started" and the program is terminated as if nobody waiting for non-daemon threads here.
What can be the reason of it?
When you run your code from main it creates both beans, thus two threads - daemon and non-daemon. As long as non-daemon thread is running, your application won't exit. So it works.
It's different when run from JUnit. As soon as JUnit test method completes (and it completes immediately after the Spring context is up), JUnit assumes your tests are done. Thus it kills all your threads and basically the whole JVM.
Remember your Waitor1 bean spawns a background thread which JUnit doesn't care about. As soon as you leave #Test method JUnit will just stop everything.
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.