How to Ensure Method is called before Object is Destroyed? - java

I've written a custom logging Class that behaves very similarly to a PrintWriter like System.out or System.err. The main difference is that when myLogger.printf("Hello World!\n"); is called, the data isn't written directly to the log file, but instead to an internal queue, and this queue only gets flushed to the output file via the flush(); method. So use of the code looks like this:
myLogger.println("Line 1.");
myLogger.println("Line 3.");
myLogger.println("Actually that was Line 2. THIS is Line 3!");
myLogger.flush();
Which should give an output that (sort of) looks like this:
2016-03-30 15:44:45::389> Line 1.
2016-03-30 15:44:45::390> Line 3.
2016-03-30 15:44:45::395> Actually that was Line 2. THIS is Line 3!
However, the problem I have is when users make mistakes. Namely, they forget to call flush(), and the data they've written to the logger never gets dumped to the file, and the program closes without ever flushing the data.
I can't flush after every single call, because it would defeat the purpose of writing this class in the first place. And having the system manage automatic flushing would be similarly self-defeating.
My idea was to put a call to flush() inside the finalize() method of the object, but as I've read from several other articles on this site, there's no guarantee that finalize() will ever be called.
Just for clarity's sake, this is what the flush() method looks like:
public void flush() {
open();
while(!unwrittenLogs.isEmpty()) {
String line = unwrittenLogs.poll();
log.print(line);
}
close();
}
private void open() {
if(log == null) {
try {
log = new PrintWriter(new FileOutputStream(logFile, true));
} catch (FileNotFoundException e) {
System.err.printf("Unable to open Log File.\n%s\n",e.getMessage());
e.printStackTrace(System.err);
}
}
}
private void close() {
if(log != null) {
log.close();
log = null;
}
}
So what is my best option to ensure that the logger is flushed before the program quits?

Put your method into the finalize method, like this:
#Override protected void finalize() throws Throwable {
// TODO Auto-generated method stub
// do some crazy stuff here
super.finalize();
}
This is and example for object destruction.
For saving the data before the JVM gets shut down, use shutdown hooks:
public static void main(final String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override public void run() {
// TODO Auto-generated method stub
// do the other crazy stuff in here
super.run();
}
});
}
But both will not be a 100% safe to use.
1) You can close the JVM without all finalizers being run
2) If you kill the JVM process via task manager / kill signal, the shutdown hooks wont be triggered

You've asked two different questions: how to ensure that your loggers' flush() method is invoked before that object is collected, and how to ensure that it is invoked before the program quits. As you gathered from your research, the logger might not be collected before the program quits, therefore a finalizer cannot guarantee that the method will be called.
If you would be satisfied with the logger being ineligible for GC prior to VM shutdown, then you could register a shutdown hook with the runtime, that flushes the logger. Such a hook would need to hold a reference to the logger, and the runtime will hold on to a reference to the hook (an unstarted Thread) until it shuts down, so the logger will remain ineligible for GC until the runtime executes its shutdown hooks.

An alternative approach to a flushable writer:
use a TransferQueue<LogItem> implementation
create a separate log writer thread
do a take() on the queue. [blocking]
open log file, optionally do truncation and log rotation as desired at this point
write taken item, drain additional items with poll() [non-blocking]
flush and close log file
if(application still running) then goto 3
This approach has several advantages:
the log thread will suffer the IO and flush costs, not the threads executing your business logic
it's thread-safe as there is only one writing thread
log item submission is lock-free as long as the TransferQueue implementation is, such as LinkedTransferQueue
the logger thread will keep the VM alive until logs are written, assuming thread.setDaemon(false), which is the default.

Related

Checking if a Thread is sleeping always returns true

I currently have the following problem:
I have made a 'Cache Updater Thread', which checks for updates and then sleeps for some amount of time. I have also build a Button, which enables the user to check for updates manually. The Thread is built like this:
public static Thread cacheUpdater = new Thread(new Runnable() {
int milliSecondSleepTime = 10000;
public void run() {
try {
cacheUpdater.setPriority(Thread.MIN_PRIORITY);
//Infinite loop
while (!terminate) {
syncStatus.set(0);
//Check for updates with some methods, not important here.
syncStatus.set(1);
Thread.sleep(this.milliSecondSleepTime);
}
}
catch (InterruptedException e) {
//First check if it is termination time
if (!terminate) {
syncStatus.set(0);
this.run();
}
}
catch (Exception e) {
System.out.println(e);
}
return;
}
});
If the user clicks the manual-update button, the following code is being runned:
#FXML public void syncOnRequest() {
//Only call interrupt, because then it will start again when terminate is still false
CacheManager.cacheUpdater.interrupt();
System.out.println(CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING));
while (!CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING)) {
//LOOP FOREVER
}
//Some code that needs to be executed after the cache is updated
}
I would like to continue executing code in the syncOnRequest() method, when the cache updater is ready with its manual update. I had the idea to check if it is sleeping, but this is not working, because the System.out.println() immediately returns true. I have measured the time it takes to do the update, and its between 200 and 400 ms.
What am I doing wrong here? And why is it always returning true?
Additional question: sometimes a click on the button just kills the Thread, because it just woke up. The InterruptedException is not thrown.
How can I make sure the Thread will also restart in that case?
Note that Thread#interrupt() is the only polite way to ask your thread to interrupt itself (unless you explicitly implement another). Using it to restart the check is therefore a bad practice. So is checking the thread state for synchronization purposes and exposing the thread that keeps your cache up-to-date to external clients.
You manager should have a updateCache() method you will call directly from UI code and auto-update thread will call the same method periodically*. In that method, make sure that access to your cached data is either correctly synchronized or it happens atomically.
*) Instead of implementing your own periodic thread, consider using
Timer and TimerTask classes as well as making it a daemon thread.

Kill or stop a endless/not-returning-value thread in Java

I have a function in Java. It normally returns a value after it completes its task. However, in some conditions it returns nothing. I create a runnable and run this function as a thread. However, because of its not returning a value, it does not finish although it does its task. The process stays alive because it waits a returning value. Is there a way to kill this thread after it is triggered or after a timeout? Stop() or Destroy() did not work. During debug, the thread is seen as alive and I want it to bi deleted/removed
Runnable runnable = new Runnable() {
#Override
public void run() {
int stat = RunMyFunction();
}
};
Thread thread = new Thread(runnable);
thread.start();
Java does not support killing a thread via any method on java.lang.Thread.
stop() and destroy() do look promising at first glance, but they have both been deprecated.
The documentation for destroy states:
This method was originally designed to destroy this thread without any cleanup. However, the method was never implemented. If if were to be implemented, it would be deadlock-prone
and stop:
This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior.
Thus when the documentation says 'deprecated', what it really means is that they are broken and must never be used!?! The Java API designers put a lot of work into backwards compatibility of their APIs, where other languages would have removed these methods Sun decided to keep them as their internal guides (rightly or wrongly) do not permit the removal of a public api method.
So, the question remains. How is one to get a thread to exit from another thread? Sadly one must go out of ones way to poll an exit variable. This can be a custom variable, or it can be a standard flag within java.lang.Thread that is accessible via 'interrupted()'. The advantage of using interrupted() is that other Java APIs such as IO support this flag during otherwise blocking API calls and will exit throwing an InterruptedException. The detection of calling interrupt() is not immediate, as it sets a flag and relies on the Thread to poll the variable at some point in the future.
Oracle offers a tutorial on how to code using interrupt here.
The real problem you have is that RunMyFunction sometimes never terminates. As others have already stated, killing a thread is not intended in Java, so there is no good way to do it. Instead, you should reason about why you call a possibly non-terminating method. This looks like a code smell. Do the following:
If you are the author of RunMyFunction, make sure that it always terminates or it can be interrupted. You can do this by checking Thread.currentThread().isInterrupted() and throwing an InterruptedException when it is. E.g:
void run(){
while(...){ // this loop sometimes runs forever
if(Thread.currentThread().isInterrupted())
throw new InterruptedException(); // Now, we can "kill" this thread here
}
}
Using ExecuterService you can specify a timeout.
ExecutorService executor = Executors.newFixedThreadPool(1);
List<Callable<String>> tasks = new ArrayList<Callable<String>>();
tasks.add(new Callable<String>() {
#Override
public String call() throws Exception {
int stat = RunMyFunction();
return "Execution Finished";
}
});
new Thread(new Runnable() {
#Override
public void run() {
try {
executor.invokeAll(tasks, 10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
invokeAll(...) is a blocking call so i've added inside a new thread.
Solution 1: Timed run: If you want a method to return or throw an exception after a specified amount of time, use the following method to execute the method on a background thread while waiting for it to complete:
public static void timedRun(Runnable r, long timeout, TimeUnit unit)
throws InterruptedException, TimeoutException {
Future<?> task = executor.submit(r);
try {
task.get(timeout, unit);
} catch (ExecutionException e) {
throw launderThrowable(e.getCause());
} finally {
task.cancel(true);
}
}
private static RuntimeException launderThrowable(Throwable t) {
if (t instanceof RuntimeException) return (RuntimeException)t;
else if (t instanceof Error) throw (Error)t;
else throw new IllegalStateException("Not unchecked", t);
}
(Source: Goetz, Brian, Bloch, Joshua, Bowbeer, Joseph, Lea, Doug, Holmes, David and Peierls, Tim. Java Concurrency in Practice. : Addison-Wesley Longman, Amsterdam, 2006. Listing 5.13 and 7.10)
For executor, you can either create a new one using Executor.newSingleThreadExecutor(), or reuse an existing one.
But be warned: Although this method is guaranteed to return or throw an exception after the specified timeout, it cannot guarantee that the runnable will really stop! It interrupts the executing thread, but if the runnable does not react to thread interruption (e.g. by internally checking Thread.interrupted()), it may continue to run in the background - possibly forever - occupying a thread! But at least it does not block.
Solution 2: Timed run with custom threads: If there is any possibility beside thread interruption to cancel your method call, you can still use the approach above, but then you have to use an Executor with custom ThreadFactory that creates a special Thread instance with overridden interrupt method:
Executor executor = Executor.newSingleThreadExecutor(r -> new WsdlThread(r));
public class WsdlThread extends Thread {
public WsdlThread(Runnable r) { super(r); }
public void interrupt() {
try {
// TODO: do something that will interrupt the wsdl call
// e.g. close connection to server, etc.
// example: ((WsdlRunnable)r).getWsdlConnection().close();
} finally {
super.interrupt();
}
}
}
If this isn't possible too, and Thread.stop() doesn't work either, this last solution might work:
Solution 3: Start non-cancellable call in another JVM:
Use Runtime.exec to start another JVM and execute the method call there (See Executing a Java application in a separate process for more info on how to do this). Runtime.exec will return a Process object, which represents the running process.
You can kill it by calling destroy() or destroyForcibly().

Why should we not swallow the InterruptedException

I am very confused and not able to understand why InterruptedException should not be swallowed.
The article from IBM says
When a blocking method detects interruption and throws InterruptedException, it clears the interrupted status. If you catch InterruptedException but cannot rethrow it, you should preserve evidence that the interruption occurred so that code higher up on the call stack can learn of the interruption and respond to it if it wants to
public class TaskRunner implements Runnable {
private BlockingQueue<Task> queue;
public TaskRunner(BlockingQueue<Task> queue) {
this.queue = queue;
}
public void run() {
try {
while (true) {
Task task = queue.take(10, TimeUnit.SECONDS);
task.execute();
}
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();//preserve the message
return;//Stop doing whatever I am doing and terminate
}
}
}
Also,Java Concurrency in Practice discusses this in more detail in Chapter 7.1.3: Responding to Interruption. Its rule is:
Only code that implements a thread's interruption policy may swallow an interruption request. General-purpose task and library code should never swallow interruption requests.
1.Can anyone explain how can code in higher call stack make use of the status set by Thread.currentThread().interrupt(); in catch block when the thread is terminated?
Also Please explain the above rule?
Take a look at this example which let's assume runs in a thread/thread-pool context.
public void run() {
// Honor interrupts so that you can stop/kill the task
while (!Thread.currentThread().interrupted()) {
this.doSomeChunkOfWork();
}
}
The above code is a good example of how you would write a task which can be interrupted and processes data in chunks (think of reading from some source and processing data in parts). Now let's assume doSomeChunkOfWork is interrupted and you catch an exception. Unless you set the flag again or maintain the interrupt status of the flag, the run method won't be able to know that the processing deep down the call stack was interrupted when the method call returns which messes up our good logic.
This is the reason why you always set the status back so that methods down the call stack are aware of whether the thread was really interrupted or not. An analogy I would like to think for this is "don't sweep dirt under the rug". :)

Java Multithreaded - Better way to cancel Future task with database and http connections?

I am having difficulty trying to correctly program my application in the way I want it to behave.
Currently, my application (as a Java Servlet) will query the database for a list of items to process. For every item in the list, it will submit an HTTP Post request. I am trying to create a way where I can stop this processing (and even terminate the HTTP Post request in progress) if the user requests. There can be simultaneous threads that are separately processing different queries. Right now, I will stop processing in all threads.
My current attempt involves implementing the database query and HTTP Post in a Callable class. Then I submit the Callable class via the Executor Service to get a Future object.
However, in order properly to stop the processing, I need to abort the HTTP Post and close the database's Connection, Statement and ResultSet - because the Future.cancel() will not do this for me. How can I do this when I call cancel() on the Future object? Do I have to store a List of Arrays that contains the Future object, HttpPost, Connection, Statement, and ResultSet? This seems overkill - surely there must be a better way?
Here is some code I have right now that only aborts the HttpPost (and not any database objects).
private static final ExecutorService pool = Executors.newFixedThreadPool(10);
public static Future<HttpClient> upload(final String url) {
CallableTask ctask = new CallableTask();
ctask.setFile(largeFile);
ctask.setUrl(url);
Future<HttpClient> f = pool.submit(ctask); //This will create an HttpPost that posts 'largefile' to the 'url'
linklist.add(new tuple<Future<HttpClient>, HttpPost>(f, ctask.getPost())); //storing the objects for when I cancel later
return f;
}
//This method cancels all running Future tasks and aborts any POSTs in progress
public static void cancelAll() {
System.out.println("Checking status...");
for (tuple<Future<HttpClient>, HttpPost> t : linklist) {
Future<HttpClient> f = t.getFuture();
HttpPost post = t.getPost();
if (f.isDone()) {
System.out.println("Task is done!");
} else {
if (f.isCancelled()) {
System.out.println("Task was cancelled!");
} else {
while (!f.isDone()) {
f.cancel(true);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("!Aborting Post!");
try {
post.abort();
} catch (Exception ex) {
System.out.println("Aborted Post, swallowing exception: ");
ex.printStackTrace();
}
}
}
}
}
}
Is there an easier way or a better design? Right now I terminate all processing threads - in the future, I would like to terminate individual threads.
I think keeping a list of all the resources to be closed is not the best approach. In your current code, it seems that the HTTP request is initiated by the CallableTask but the closing is done by somebody else. Closing resources is the responsibility of the one who opened it, in my opinion.
I would let CallableTask to initiate the HTTP request, connect to database and do it's stuff and, when it is finished or aborted, it should close everything it opened. This way you have to keep track only the Future instances representing your currently running tasks.
I think your approach is correct. You would need to handle the rollback yourself when you are canceling the thread
cancel() just calls interrupt() for already executing thread. Have a look here
http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html:
As it says
An interrupt is an indication to a thread that it should stop what it
is doing and do something else. It's up to the programmer to decide
exactly how a thread responds to an interrupt, but it is very common
for the thread to terminate.
Interrupted thread would throw InterruptedException
when a thread is waiting, sleeping, or otherwise paused for a long
time and another thread interrupts it using the interrupt() method in
class Thread.
So you need to explicitly code for scenarios such as you mentioned in executing thread where there is a possible interruption.

How can I "capture" System.exit(-1) from different thread?

I have the following
System.setSecurityManager(new SecurityManager() {
#Override
public void checkExit(int status) {
super.checkExit(status);
//custom exception extends SecurityException
throw new SystemExitCalledException();
}
});
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
//never reaches here somehow...
//maybe some3rdPartyStaticMethod sets this, too?
}
});
try {
//this method spawns threads and some call System.exit().
some3rdPartyStaticMethod.invoke(null, new Object[]{args});
} catch (SystemExitCalledException e) {
//it never reaches here because
//SystemExitCalledException is thrown on different thread??
//
}
Is there a way to prevent some3rdPartyStaticMethod's spawned thread's System.exit() call from halting jvm?
You can start the code in a separate process and communicate with it using RMI. If the third party code calls System.exit and kills its process, your process can continue to run and recreate the child process if necessary.
Note that there are some caveats with this approach:
The two processes don't share the same heap space.
You will need to marshal all data that is passed between the two processes. This means that the data must be serializable.
There will be a considerable overhead for every method call. This may give performance problems if you need to make many calls per second.
Writing a custom SecurityManager policy should help -- I've never done this myself :)
According to this post (scroll down to the bottom):
However, when anything in the VM tries to call System.exit(), the VM exits. Since this includes a brutal shotdown of mvn, the normal mvn process is interrupted. A SecurityManager can be used to prevent code from calling System.exit(), but nobody mentions the side-effects.
A colleague of mine mentioned that you can setup your policies system-wide, per-user and as a system-property when starting the VM and after a quick test this has proven to solve my problem. I've since managed to figure out how to set my own policy from my code (before setting up the SecurityManager) and this solves my problems.
I used the following code:
//Setup security to prevent System.exit()
SecurityManager sm = System.getSecurityManager();
URL policy = getClass().getClassLoader().getResource("jsdoc.policy");
System.setProperty("java.security.policy", policy.toString());
System.setSecurityManager(new JSDocSecurityManager(getLog()));
With a simple, wide-open, policy file reading this:
grant {
permission java.security.AllPermission;
};
If it works it supposed to capture the System.exit() request and throw a SecurityException instead

Categories

Resources