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;
}
}
Related
I've been all over the internet and the Java docs regarding this one; I can't seem to figure out what it is about do while loops I'm not understanding. Here's the background: I have some message handler code that takes some JSON formatted data from a REST endpoint, parses it into a runnable task, then adds this task to a linked blocking queue for processing by the worker thread. Meanwhile, on the worker thread, I have this do while loop to process the message tasks:
do {
PublicTask currentTask = pubMsgQ.poll();
currentTask.run();
} while(pubMsgQ.size() > 0);
pubMsgQ is a LinkedBlockingQueue<PublicTask> (PublicTask implements the Runnable interface). I can't see any problems with this loop (obviously, or else I wouldn't be here), but this is how it behaves during execution: Upon entering the do block, pubMsgQ is polled and returns the runnable task as expected. The task is then run successfully with expected results, but then we get to the while statement. Now, according to the Java docs, poll() should return and remove the head of the queue, so I should expect that pubMsgQ.size() will return 0, right? Wrong I guess, because somehow the while statement passes and the program enters the do block again; of course this time pubMsgQ.poll() returns null (as I would have expected it should) and the program crashes with NullPointerException. What? Please explain like I'm five...
EDIT:
I decided to leave my original post as is above; because I think I actually explain the undesired behavior of that specific piece of the code quite succinctly (the loop is being executed twice while I'm fairly certain there is no way the loop should be executing twice). However, I realize that probably doesn't give enough context for that loop's existence and purpose in the first place, so here is the complete breakdown for what I am actually trying to accomplish with this code as I am sure there is a better way to implement this altogether anyways.
What this loop is actually a part of is a message handler class which implements the MessageHandler interface belonging to my Client Endpoint class [correction from my previous post; I had said the messages coming in were JSON formatted strings from a REST endpoint. This is technically not true: they are JSON formatted strings being received through a web socket connection. Note that while I am using the Spring framework, this is not a STOMP client; I am only using the built-in javax WebSocketContainer as this is more lightweight and easier for me to implement]. When a new message comes in onMessage() is called, which passes the JSON string to the MessageHandler; so here is the code for the entire MessageHandler class:
public class MessageHandler implements com.innotech.gofish.AutoBrokerClient.MessageHandler {
private LinkedBlockingQueue<PublicTask> pubMsgQ = new LinkedBlockingQueue<PublicTask>();
private LinkedBlockingQueue<AuthenticatedTask> authMsgQ = new LinkedBlockingQueue<AuthenticatedTask>();
private MessageLooper workerThread;
private CyclicBarrier latch = new CyclicBarrier(2);
private boolean running = false;
private final boolean authenticated;
public MessageHandler(boolean authenticated) {
this.authenticated = authenticated;
}
#Override
public void handleMessage(String msg) {
try {
//Create new Task and submit it to the message queue:
if(authenticated) {
AuthenticatedTask msgTsk = new AuthenticatedTask(msg);
authMsgQ.put(msgTsk);
} else {
PublicTask msgTsk = new PublicTask(msg);
pubMsgQ.put(msgTsk);
}
//Check status of worker thread:
if(!running) {
workerThread = new MessageLooper();
running = true;
workerThread.start();
} else if(running && !workerThread.active) {
latch.await();
latch.reset();
}
} catch(InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
private class MessageLooper extends Thread {
boolean active = false;
public MessageLooper() {
}
#Override
public synchronized void run() {
while(running) {
active = true;
if(authenticated) {
do {
AuthenticatedTask currentTask = authMsgQ.poll();
currentTask.run();
if(GoFishApplication.halt) {
GoFishApplication.reset();
}
} while(authMsgQ.size() > 0);
} else {
do {
PublicTask currentTask = pubMsgQ.poll();
currentTask.run();
} while(pubMsgQ.size() > 0);
}
try {
active = false;
latch.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
}
You may probably see where I'm going with this...what this Gerry-rigged code is trying to do is act as a facsimile for the Looper class provided by the Android Development Kit. The actual desired behavior is as messages are received, the handleMessage() method adds the messages to the queue for processing and the messages are processed on the worker thread separately as long as there are messages to process. If there are no more messages to process, the worker thread waits until it is notified by the handler that more messages have been received; at which point it resumes processing those messages until the queue is once again empty. Rinse and repeat until the user stops the program.
Of course, the closest thing the JDK provides to this is the ThreadPoolExecutor (which I know is probably the actual proper way to implement this); but for the life of me I couldn't figure out how to for this exact case. Finally, as a quick aside so I can be sure to explain everything fully, The reason why there are two queues (and a public and authenticated handler) is because there are two web socket connections. One is an authenticated channel for sending/receiving private messages; the other is un-authenticated and used only to send/receive public messages. There should be no interference, however, given that the authenticated status is final and set at construction; and each Client Endpoint is passed it's own Handler which is instantiated at the time of server connection.
You appear to have a number of concurrency / threading bugs in your code.
Assumptions:
It looks like there could be multiple MessageHandler objects, each with its own pair of queues and (supposedly) at most one MessageLooper thread. It also looks as if a given MessageHandler could be used by multiple request worker threads.
If that is the case, then one problem is that MessageHandler is not thread-safe. Specifically, the handleMessage is accessing and updating fields of the MessageHandler instance without doing any synchronization.
Some of the fields are initialized during object creation and then never changed. They are probably OK. (But you should declare them as final to be sure!) But some of the variables are supposed to change during operation, and they must be handled correctly.
One section that rings particular alarm bells is this:
if (!running) {
workerThread = new MessageLooper();
running = true;
workerThread.start();
} else if (running && !workerThread.active) {
latch.await();
latch.reset();
}
Since this is not synchronized, and the variables are not volatile:
There are race conditions if two threads call this code simultaneously; e.g. between testing running and assigning true to it.
If one thread sets running to true, there are no guarantees that a second thread will see the new value.
The net result is that you could potentially get two or more MessageLooper threads for a given set of queues. That breaks your assumptions in the MessageLooper code.
Looking at the MessageLooper code, I see that you have declared the run method as synchronized. Unfortunately, that doesn't help. The problem is that the run method will be synchronizing on this ... which is the specific instance of MessageLooper. And it will acquire the lock once and release it once. On short, the synchronized is wrong.
(For Java synchronized methods and synchronized blocks to work properly, 1) the threads involved need to synchronize on the same object (i.e. the same primitive lock), and 2) all read and write operations on the state guarded by the lock need to be done while holding the lock. This applies to use of Lock objects as well.)
So ...
There is no synchronization between a MessageLooper thread and any other threads that are adding to or removing from the queues.
There are no guarantees that the MessageLooper thread will notice changes to the running flag.
As I previously noted, you could have two or more MessageLooper polling the same pair of queues.
In short, there are lots of possible explanations for strange behavior in the code in the Question. This includes the specific problem you noticed with the queue size.
Writing correct multi-threaded code is difficult. This is why you should be using an ExecutorService rather than attempting to roll your own code.
But it you do need to roll your own concurrency code, I recommend buying and reading "Java: Concurrency in Practice" by Brian Goetz et al. It is still the only good textbook on this topic ...
Suppose I have the following code:
private final ReentrantLock resourcesLock = new ReentrantLock(true);
private Condition resourcePresentCondition= resourcesLock.newCondition();
public void requestRes() throws InterruptedException {
resourcesLock.lock();
try {
if(resources.isEmpty()) {
if(!resourcePresentCondition.await(Config.STARVE_TIME_SECONDS, TimeUnit.SECONDS)) {
if(resources.isEmpty()) {
return;
}
}
}
//No resources left if other threads gather them first
Resource resource = resources.removeFirst();
} finally {
resourcesLock.unlock();
}
}
Now, multiple threads enter the requestRes() method and if no resources are present, they all wait on the condition. Another method generates resources and calls resourcePresentCondition.signalAll(). After this, if time has not run out(or if it did and there are resources present -- just to avoid cases where it all happens at the same time), a resource is consumed.
The problem is that sometimes resources are emptied and threads that got the signal for resourcePresentCondition throw exceptions because resources list is empty(.removeFirst() exception).
What would be the best solution to avoid this and make the threads resume the wait(not start over) for resourcePresentCondition?
The easiest way to do this would be to use just signal() instead of signalAll, calling signal() once for every resource added. This makes sure that each thread that was signaled is guaranteed to have 1 resource to consume.
This makes the other threads wait until signalled or timeout occurs. There's no way to resume an existing await(), and you don't want to start writing custom logic to keep track of the time that has been spent waiting.
Since you're using a fair lock (new ReentrantLock(true);) (as you should in this case) it doesn't even make sense to signal all of the threads. You don't want a consumer that just had a resource to be competing for another one.
A different approach which would simplify things would be to use a fair Semaphore.
// Consumer
private final Semaphore semaphore = new Semaphore(0, true);
public void requestRes() throws InterruptedException {
if(!semaphore.tryAcquire(Config.STARVE_TIME_SECONDS, TimeUnit.SECONDS))
return; // No resource available, and timed out
Resource resource = resources.removeFirst();
}
// Producer, giving out as many semaphores as resources produced
semaphore.release(resources.size());
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.
I am using the Java ExecutorService framework to submit callable tasks for execution.
These tasks communicate with a web service and a web service timeout of 5 mins is applied.
However I've seen that in some cases the timeout is being ignored and thread 'hangs' on an API call - hence, I want to cancel all the tasks that take longer than say, 5 mins.
Currently, I have a list of futures and I iterate through them and call future.get until all tasks are complete. Now, I've seen that the future.get overloaded method takes a timeout and throws a timeout when the task doesnt complete in that window. So I thought of an approach where I do a future.get() with timeout and in case of TimeoutException I do a future.cancel(true) to make sure that this task is interrupted.
My main questions
1. Is the get with a timeout the best way to solve this issue?
2. Is there the possibility that I'm waiting with the get call on a task that hasnt yet been placed on the thread pool(isnt an active worker). In that case I may be terminating a thread that, when it starts may actually complete within the required time limit?
Any suggestions would be deeply appreciated.
Is the get with a timeout the best way to solve this issue?
This will not suffice. For instance, if your task is not designed to response to interruption, it will keep on running or be just blocked
Is there the possibility that I'm waiting with the get call on a task that hasnt yet been placed on the thread pool(isnt an active worker). In that case I may be terminating a thread that, when it starts may actually complete within the required time limit?
Yes, You might end up cancelling as task which is never scheduled to run if your thread-pool is not configured properly
Following code snippet could be one of the way you can make your task responsive to interruption when your task contains Non-interruptible Blocking. Also it does not cancel the task which are not scheduled to run. The idea here is to override interrupt method and close running tasks by say closing sockets, database connections etc. This code is not perfect and you need to make changes as per requirements, handle exceptions etc.
class LongRunningTask extends Thread {
private Socket socket;
private volatile AtomicBoolean atomicBoolean;
public LongRunningTask() {
atomicBoolean = new AtomicBoolean(false);
}
#Override
public void interrupt() {
try {
//clean up any resources, close connections etc.
socket.close();
} catch(Throwable e) {
} finally {
atomicBoolean.compareAndSet(true, false);
//set the interupt status of executing thread.
super.interrupt();
}
}
public boolean isRunning() {
return atomicBoolean.get();
}
#Override
public void run() {
atomicBoolean.compareAndSet(false, true);
//any long running task that might hang..for instance
try {
socket = new Socket("0.0.0.0", 5000);
socket.getInputStream().read();
} catch (UnknownHostException e) {
} catch (IOException e) {
} finally {
}
}
}
//your task caller thread
//map of futures and tasks
Map<Future, LongRunningTask> map = new HashMap<Future, LongRunningTask>();
ArrayList<Future> list = new ArrayList<Future>();
int noOfSubmittedTasks = 0;
for(int i = 0; i < 6; i++) {
LongRunningTask task = new LongRunningTask();
Future f = execService.submit(task);
map.put(f, task);
list.add(f);
noOfSubmittedTasks++;
}
while(noOfSubmittedTasks > 0) {
for(int i=0;i < list.size();i++) {
Future f = list.get(i);
LongRunningTask task = map.get(f);
if (task.isRunning()) {
/*
* This ensures that you process only those tasks which are run once
*/
try {
f.get(5, TimeUnit.MINUTES);
noOfSubmittedTasks--;
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} catch (TimeoutException e) {
//this will call the overridden interrupt method
f.cancel(true);
noOfSubmittedTasks--;
}
}
}
}
execService.shutdown();
Is the get with a timeout the best way to solve this issue?
Yes it is perfectly fine to get(timeout) on a Future object, if the task that the future points to is already executed it will return immediately. If the task is yet to be executed or is being executed then it will wait until timeout and is a good practice.
Is there the possibility that I'm waiting with the get call on a task
that hasnt yet been placed on the thread pool(isnt an active worker)
You get Future object only when you place a task on the thread pool so it is not possible to call get() on a task without placing it on thread pool. Yes there is a possibility that the task has not yet been taken by a free worker.
The approach that you are talking about is ok. But most importantly before setting a threshold on the timeout you need to know what is the perfect value of thread pool size and timiout for your environment. Do a stress testing which will reveal whether the no of worker threads that you configured as part of Threadpool is fine or not. And this may even reduce the timeout value. So this test is most important i feel.
Timeout on get is perfectly fine but you should add to cancel the task if it throws TimeoutException. And if you do the above test properly and set your thread pool size and timeout value to ideal than you may not even need to cancel tasks externally (but you can have this as backup). And yes sometimes in canceling a task you may end up canceling a task which is not yet picked up by the Executor.
You can of course cancel a Task by using
task.cancel(true)
It is perfectly legal. But this will interrupt the thread if it is "RUNNING".
If the thread is waiting to acquire an intrinsic lock then the "interruption" request has no effect other than setting the thread's interrupted status. In this case you cannot do anything to stop it. For the interruption to happen, the thread should come out from the "blocked" state by acquiring the lock it was waiting for (which may take more than 5 mins). This is a limitation of using "intrinsic locking".
However you can use explicit lock classes to solve this problem. You can use "lockInterruptibly" method of the "Lock" interface to achieve this. "lockInterruptibly" will allow the thread to try to acquire a lock while remaining responsive to the interruption. Here is a small example to achieve that:
public void workWithExplicitLock()throws InterruptedException{
Lock lock = new ReentrantLock();
lock.lockInterruptibly()();
try {
// work with shared object state
} finally {
lock.unlock();
}
}
What is the best way to handle RejectedExecutionException while using a ThreadPoolExecutor in Java?
I want to ensure that the task submitted should not be overlooked and should surely get executed. As of now there are no hard real time requirements to get the task done.
One of the things I thought could be done was waiting in a loop till I know that there is space in the runnable queue, and then go on and add it to the queue.
Would be glad if people can share their experiences.
Adding the possible solution I though of:
while(executor.getQueue().remainingCapacity <= 0){
// keep looping
Thread.sleep(100);
};
//if the loop exits ,indicates that we have space in the queue hence
//go ahead and add to the queue
executor.execute(new ThreadInstance(params));
I would change the behaviour of your queue. e.g.
public class MyBlockingQueue<E> extends ArrayBlockingQueue<E> {
private final long timeoutMS;
public MyBlockingQueue(int capacity, long timeoutMS) {
super(capacity);
this.timeoutMS = timeoutMS;
}
#Override
public boolean offer(E e) {
try {
return super.offer(e, timeoutMS, TimeUnit.MILLISECONDS);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
return false;
}
}
}
This will wait for the queue to drain before giving up.
If you have constrained your thread pool to only allow a certain number of concurrent threads (generally a good thing), then the application needs to somehow push-back on the calling code, so when you receive a RejectedExecutionException from the ThreadPoolExecutor you need to indicate this to the caller and the caller will need to handle the retry.
An analogous situation is a web server under heavy load. A client connects, the web server should return a 503 - Service Unavailable (generally a temporary condition) and the client decides what to do about it.