I have the following code:
public class LogWriter implements Runnable {
private static BlockingQueue<LogRecord> logQueue;
static {
logQueue = new ArrayBlockingQueue<LogRecord>(30);
}
#Override
public void run() {
Integer errorNo = 0;
configureLogger();
while (true) {
try {
LogRecord record = logQueue.take();
consumeLogRecord(record);
System.out.println(++errorNo + " - Logged error in file '" + LoggerConfig.LOG_PATH + "'");
record = null;
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
}
This is part of a logger for a LibreOffice pluggin written in Java. When LibreOffice is closing, it simply kills it's plugins (as I can tell so far, not sure of it), but not before sending a signal to them that it is closing, which I can detect in my code (through the UNO API). After I receive the termination signal from LibreOffice, I want to flush my LogRecord queue to the log file and change that while(true) to false so the method run() can finish appropriately, releasing the resources it have. So my question is, how can I tell the JVM that waiting for this operation is of high priority and it shouldn't terminate before finishing it?
The advice about shutdown hooks must be taken with a large grain of salt. The shutdown hook is a last resort device where you can try to salvage what you couldn't possibly by any other means. You can't rely on any normal assumption, such as that System.out is still open, that your log file is still open, that even the filesystem is available, and so on.
A use case for a shutdown hook is to try to gracefully close acquired resources, with no attempt at further data transfer.
The approach you should take is:
inform yourself exactly what terms LibreOffice gives you: do you have a certain timeout within which to complete your work?
minimize the work pending at any point in time, thereby maximizing your chance to have it completed within the timeout.
You can use.
Runtime.getRuntime().addShutdownHook(Thread);
Shutdown hooks will be the best option to go.
Related
I have a Console-Java game. The score from the game will be saved in a JSON file if Ctrl+C is pressed. The process to save the score in a JSON file works. But I don't know, how to detect Ctrl+C from the console and if this happens, I will save the score (just a method call).
With KeyListener it doesn't work on the console (only with JFrame as far as I know).
I couldn't find a solution to my problem on the internet.
Do I have to do it with Runtime? I have tried it, but it didn't work...
Runtime.getRuntime().addShutdownHook(new Thread()
{
public void run()
{
Test.mainThread.interrupt();
}
});
There are similar questions on Stackoverflow, but not for use on the console Catching Ctrl+C in Java
Adding a shutdown hook is the right way to do it, but Test.mainThread.interrupt(); probably will not work. The JVM is already shutting down. Your mainThread is unlikely to have time to respond to an interrupt; once all shutdown hooks finish, Java terminates.
Just have your shutdown hook explicitly perform whatever actions you need taken:
Runtime.getRuntime().addShutdownHook(new Thread()
{
#Override
public void run()
{
try
{
Test.saveScore();
}
catch (IOException e)
{
System.err.println("Couldn't save score before terminating.");
e.printStackTrace();
}
}
});
We know that CTRL-C closes the application and shuts down the JVM. And since it is a normal shutdown, it runs the shutdown hooks. So creating a shutdown hook is a correct approach:
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
// Do something to save the score
}));
Note that we're passing a Runnable here as the shutdown task. So we can pass an object that has the required functionality:
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
gameScores.save(); // assuming we have a gameScores object in this scope
}));
Your initial attempt by interrupting the thread can be viewed as a variant of this approach. Instead of passing the business object - gameScores - we can pass the thread to interrupt it later. But it's better to operate on the business level.
I am working on an application that needs to launch a process and wait for its output. Sometimes the process crashes (very often,) but is not really an issue since I have mitigation tasks. The problem is that Windows detects the process crashed and prompts for user input, to either check for a solution online, or just close the program.
I tried to solve this by waiting for the process to complete in a Runnable submitted to an ExecutorService and using the Future returned to specify a timeout. Speed is not really a concern for the application, and the external process is supposed to run for just a couple of seconds.
This is the code I am using:
final Process process = ...
final ExecutorService service = Executors.newSingleThreadExecutor();
try {
final Future<?> future = service.submit(new Runnable() {
#Override
public void run() {
try {
process.waitFor();
} catch (InterruptedException e) { /* error handling */}
}
});
future.get(10, TimeUnit.SECONDS);
} catch (final TimeoutException e) {
// The process may have crashed
process.destroy();
} catch (final Exception e) {
// error handling
} finally {
service.shutdown();
}
The code above worked well, but the crash dialog still pops up and it doesn't go away without user interaction.
This question presents a similar problem but from a .Net perspective and
proposes to suppress the pop up through the Windows registry, which I cannot do, given that its effect is global to all process in the machine.
Is there a way to prevent the dialog from being displayed at all?
or
Is there a way to detect the application crash and handle it directly
from Java without needing user interaction?
Additional details:
I don't have the source of the external process.
The external process is a console based application (i.e. no GUI.)
Preferably I'm looking for a pure Java based solution (no JNI.)
Thank you.
As already suggested you should use SetErrorMode win32 call. It won't change for the whole system but only for your process and it's children (which is what you want apparently).
The correct call seems to be :
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
See also the MSDN documentation :
http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621%28v=vs.85%29.aspx
Regards.
I have a servlet filter that carries some logic and produces output before a request is served by it's primary page. I have a new need to send out the output a few seconds later than at the moment it is generated (with ~10s delay). Because of certain poor design choices made earlier I can't move the position of the filter just to have the output sent after.
I've chosen to spawn off a thread and delay transmission of the message in there. I'm currently not taking any explicit steps to halt execution of this thread. I'm not sure if everything is getting cleaned up properly though. Should I be using join() or interrupt() or any other Thread methods to clean up safely after this?
So within the main servlet code I have something like this...
Thread t = new Thread(new MessageSender(message, 10000));
t.start();
//Carry on.. la la la
While there are other fields in this class, I just stripped out a lot of the non-essential stuff like making DB connections etc to make the point clear.
private static class MessageSender implements Runnable {
String message;
int delay;
public MessageSender(String message, int delay) {
this.message = message;
this.delay = delay;
}
public void run() {
try {
Thread.sleep(delay);
System.out.println(new java.util.Date() + ": hello world");
} catch (InterruptedException e) {
// Do blah
} catch (Exception e) {
// Do blah blah
} finally {
// Close connections and stuff
}
}
}
Your code should be fine, the VM will clean up the thread once it completes.
However, I'd advise not using raw threads like that, but instead using a java.util.concurrent.ScheduledExecutorService, creating using java.util.concurrent.Executors. It's a nicer abstraction that would better control your thread allocation.
Yes, everything will be properly cleaned up. Thread dies after finishing run() method and as you have no more references to that thread object - it will be properly garbage-collected.
Just be sure that "Thread t" object will not be referenced by anything. To be sure on that, you can use:
(new Thread(...)).start();
The servlet specification explicitly states (section "Thread safety") that request and response objects are not guaranteed to be thread-safe, and that if those objects are handed off to other threads, then the application is responsible for ensuring that these objects are synchronized and that they are accessed only within the scope of the servlet's service method. In other words, you must .join() those threads.
I've just had to answer the same question myself :)
I can acknowledge that the threads are indeed cleaned up after they complete. If you're not completely certain the spawned threads ever die, you should be able to monitor the process and see how many threads it's currently running at. If the number keeps growing, something's outta control.
On a Unix-system, you can use the ps command, but I'm rusty, so I asked google instead of reading the man-page.
One of the first hits on google was This script that lists threads for each process. Output looks like this
PID TID CLS RTPRIO STAT COMMAND WCHAN
....
16035 16047 TS - S (java)
16035 16050 TS - S (java)
16035 16054 TS - S (java)
16035 16057 TS - S (java)
16035 16058 TS - S (java)
16035 16059 TS - S (java)
16035 16060 TS - S (java)
....
And I just grep the output for the process id (pid) of the process I want to watch and count the number of lines, each one corresponding to a thread. Like this:
morten#squeeze: ~$ sh /tmp/list_threads.sh | grep 16035 | wc -l
20
So the program I'm currently watching (PID 16035) has 20 threads running.
This required no knowledge of jconsole or any changes to the code. The last part is probably the most important part, as I haven't written the program myself, so now I don't have to read and understand the program.
I am using the Javamail API connecting to my IMAP server. Everything is working great with the javax.mail.Folder.idle() method. My listener gets called when a new mail comes in. However the problem is idle blocks forever, how do I interrupt it? How do I actually stop the listening without killing my Java program?
I've tried calling Thread.interrupt() on the idle'd thread. Nothing happens. I am running out of ideas.
Performing any operation on that folder (from another thread) will cause idle() method to return immediately. So if you want to forcefully interrupt it, just call close() from a new thread.
If you read the documentation properly, and read the source code, you'll realise that you have to create a new thread for calling .idle().
Allocate that thread to a variable, and whenever you want call the interrupt() on that thread, or just ignore notifications!
If you need to get idle() going again, just rerun the thread!
I created something similar, so you might wanna check it out.
https://github.com/mofirouz/JavaPushMail/blob/master/src/main/java/com/mofirouz/javapushmail/JavaPushMailAccount.java
Good luck
A proper way to abort IDLE command is the following snippet. Note that the Folder instance should be the same as the one used to start idling. I've tested the other solutions proposed on this thread but they didn't work in my case.
IMAPFolder folder = store.getFolder("INBOX");
try {
folder.doOptionalCommand("Abort IDLE error mesage", new IMAPFolder.ProtocolCommand() {
#Override
public Object doCommand(IMAPProtocol p) throws ProtocolException {
p.idleAbort();
return Boolean.TRUE;
}
});
} catch (MessagingException e) {
e.printStackTrace();
}
In a java application,when the user hits download,establishing the remote connection and downloading the content from remote is done in a separate thread and a dialog is popped up in the screen to show the download progress. Now a cancel command has been added to the dialog inorder to provide the user with an option of cancelling the download. When the user hits cancel button, dialog can be disposed using dispose() method from the program but how can I stop/kill the thread which has already been initiated? Thread does the following task: 1.Establishes connection with remote 2.Downloads content from remote 3.stores the content locally (content is transferred via streaming)
Please help me to resolve this issue
Stopping a thread is probably the wrong way to look at. The actual resource consumed by a single thread on a desktop machine is irrelevant. Think of it as aborting the download.
If the read is blocking, then that isn't really much of a problem. You can wait until there is some data before not reading again. A more abrupt approach would be to call close on the stream (from another thread).
You need to check for a stop flag somewhere in your download routine.
public DownloadThread implements Runnable {
private boolean stop;
public void stop() { stop = true; }
public void run() {
while (!stop) {
// download a block, save it somewhere
}
}
}
Of course this lacks the necessary synchronization but that’s about how you stop a thread without using the deprecated Thread.stop().
Firstly, the stop() operation on java.util.Thread is deprecated, and its use is strongly discouraged, since it can leave things in an unstable state. It's much preferred that you send a message to the Thread's Runnable asking it to stop itself safely.
The problem you have is that your thread is doing blocking I/O operations, and so it won't receive your message until the I/O is complete.
The best you can hope for, unless someone else comes up with a better option, is to interrupt() the Thread, and hope that the I/O classes notice and stop the download.
Edit: The javadoc for Thread.interrupt() does say that I/IO can be interrupted if you use java.nio, but it's very unlikely that you are. "Normal" java.io traffic is blocking, and cannot be interrupted.
Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?
I suggest you do what Bombe suggested (with a volatile variable) and just leave the thread to die in the background, returning control back to the user. It might spend a little while fetching the last block, but if the user can carry on doing something else it doesn't matter too much. If your block sizes were relatively small the wasted bandwidth wont be too much, and the IO stuff will timeout eventually and return if the connection has gone bad.
public class Downloader {
protected final AtomicBoolean run = new AtomicBoolean(false);
protected final byte[] file;
protected volatile double progress = 0.0;
public download(URL url) {
run.set(true);
new Thread() {
#Override
public run() {
final ByteBuffer buffer = new ByteBuffer();
while(run) {
/* download chunk, e.g add to buffer, or whatever */
buffer.put(chunk);
progress = buffer.size().size() / fileTotalSize; //e.g
}
syncrhonized(Downloader.this) {
file = buffer.array();
}
}
}.start();
}
public void abort() {
run.set(false);
}
public double getProgress() {
return progress;
}
public synchronized byte[] getFile() {
return file;
}
}