I am working on an application, where I continuously read data from a Kafka topic. This data comes in String format which I then write to an xml file & store it on hard disk. Now, this data comes randomly and mostly it's supposed to come in bulk, in quick succession.
To write these files, I am using an Executor Service.
ExecutorService executor = Executors.newFixedThreadPool(4);
/*
called multiple times in quick succession
*/
public void writeContent(String message) {
try {
executor.execute(new FileWriterTask(message));
} catch(Exception e) {
executor.shutdownNow();
e.printStackTrace();
}
}
private class FileWriterTask implements Runnable{
String data;
FileWriterTask(String content){
this.data = content;
}
#Override
public void run() {
try {
String fileName = UUID.randomUUID().toString();
File file = new File("custom path" + fileName + ".xml");
FileUtils.writeStringToFile(file, data, Charset.forName("UTF-8"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
I want to know when should I shutdown my executor service. If my application was time bound, I would used awaitTermination on my executor instance, but my app is supposed to run continuously.
If in case of any exception, my whole app is killed, would it automatically shutdown my executor?
Or should I catch an unchecked exception and shutdown my executor, as I have done above in my code?
Can I choose not to explicitly shutdown my executor in my code? What are my options?
EDIT: Since my class was a #RestController class I used the following
way to shutdown my executor service
#PreDestroy
private void destroy() {
executor.shutdownNow();
if(executor != null) {
System.out.println("executor.isShutdown() = " + executor.isShutdown());
System.out.println("executor.isTerminated() = " + executor.isTerminated());
}
}
It is a good practice to shut down your ExecutorService. There are two types of shutdown that you should be aware of, shutdown() and shutdownNow().
If you're running you application on an application server with Java EE, you can also use a ManagedExecutorService, which is managed by the framework and will be shut down automatically.
Related
I have an application that receives alerts from other applications, usually once a minute or so but I need to be able to handle higher volume per minute. The interface I am using, and the Alert framework in general, requires that alerts may be processed asynchronously and can be stopped if they are being processed asynchronously. The stop method specifically is documented as stopping a thread. I wrote the code below to create an AlertRunner thread and then stop the thread. However, is this a proper way to handle terminating a thread? And will this code be able to scale easily (not to a ridiculous volume, but maybe an alert a second or multiple alerts at the same time)?
private AlertRunner alertRunner;
#Override
public void receive(Alert a) {
assert a != null;
alertRunner = new alertRunner(a.getName());
a.start();
}
#Override
public void stop(boolean synchronous) {
if(!synchronous) {
if(alertRunner != null) {
Thread.currentThread().interrupt();
}
}
}
class AlertRunner extends Thread {
private final String alertName;
public AlertRunner(String alertName) {
this.alertName = alertName;
}
#Override
public void run() {
try {
TimeUnit.SECONDS.sleep(5);
log.info("New alert received: " + alertName);
} catch (InterruptedException e) {
log.error("Thread interrupted: " + e.getMessage());
}
}
}
This code will not scale easily because Thread is quite 'heavy' object. It's expensive to create and it's expensive to start. It's much better to use ExecutorService for your task. It will contain a limited number of threads that are ready to process your requests:
int threadPoolSize = 5;
ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize);
public void receive(Alert a) {
assert a != null;
executor.submit(() -> {
// Do your work here
});
}
Here executor.submit() will handle your request in a separate thread. If all threads are busy now, the request will wait in a queue, preventing resource exhausting. It also returns an instance of Future that you can use to wait for the completion of the handling, setting the timeout, receiving the result, for cancelling execution and many other useful things.
I have some service that both consumes from an inbound queue and produces to some outbound queue (where another thread, created by this service, picks up the messages and "transports" them to their destination).
Currently I use two plain Threads as seen in the code bellow but I know that in general you should not use them anymore and instead use the higher level abstractions like the ExecutorService.
Would this make sense in my case? More specifically I mean ->
would it reduce code?
make the code more robust in case of failure?
allow for smoother thread termination? (which is helpfull when running tests)
Am I missing something important here? (maybee some other classes from java.util.concurrent)
// called on service startup
private void init() {
// prepare everything here
startInboundWorkerThread();
startOutboundTransporterWorkerThread();
}
private void startInboundWorkerThread() {
InboundWorkerThread runnable = injector.getInstance(InboundWorkerThread.class);
inboundWorkerThread = new Thread(runnable, ownServiceIdentifier);
inboundWorkerThread.start();
}
// this is the Runnable for the InboundWorkerThread
// the runnable for the transporter thread looks almost the same
#Override
public void run() {
while (true) {
InboundMessage message = null;
TransactionStatus transaction = null;
try {
try {
transaction = txManager.getTransaction(new DefaultTransactionDefinition());
} catch (Exception ex) {
// logging
break;
}
// blocking consumer
message = repository.takeOrdered(template, MESSAGE_POLL_TIMEOUT_MILLIS);
if (message != null) {
handleMessage(message);
commitTransaction(message, transaction);
} else {
commitTransaction(transaction);
}
} catch (Exception e) {
// logging
rollback(transaction);
} catch (Throwable e) {
// logging
rollback(transaction);
throw e;
}
if (Thread.interrupted()) {
// logging
break;
}
}
// logging
}
// called when service is shutdown
// both inbound worker thread and transporter worker thread must be terminated
private void interruptAndJoinWorkerThread(final Thread workerThread) {
if (workerThread != null && workerThread.isAlive()) {
workerThread.interrupt();
try {
workerThread.join(TimeUnit.SECONDS.toMillis(1));
} catch (InterruptedException e) {
// logging
}
}
}
The main benefit for me in using ThreadPools comes from structuring the work in single, independent and usually short jobs and better abstraction of threads in a ThreadPools private Workers. Sometimes you may want more direct access to those, to find out if they are still running etc. But there are usually better, job-centric ways to do that.
As for handling failures, you may want to submit your own ThreadFactory to create threads with a custom UncaughtExceptionHandler and in general, your Runnable jobs should provide good exception handling, too, in order to log more information about the specific job that failed.
Make those jobs non-blocking, since you don't want to fill up your ThreadPool with blocked workers. Move blocking operations before the job is queued.
Normally, shutdown and shutdownNow as provided by ExecutorServices, combined with proper interrupt handling in your jobs will allow for smooth job termination.
I'm trying to queue up tasks in a thread pool to be executed as soon as a worker becomes free, i have found various examples of this but in all cases the examples have been setup to use a new Worker instance for each job, i want persistent workers.
I'm trying to make a ftp backup tool, i have it working but because of the limitations of a single connection it is slow. What i ideally want to do is have a single connection for scanning directories and building up a file list then four workers to download said files.
Here is an example of my FTP worker:
public class Worker implements Runnable {
protected FTPClient _ftp;
// Connection details
protected String _host = "";
protected String _user = "";
protected String _pass = "";
// worker status
protected boolean _working = false;
public Worker(String host, String user, String pass) {
this._host = host;
this._user = user;
this._pass = pass;
}
// Check if the worker is in use
public boolean inUse() {
return this._working;
}
#Override
public void run() {
this._ftp = new FTPClient();
this._connect();
}
// Download a file from the ftp server
public boolean download(String base, String path, String file) {
this._working = true;
boolean outcome = true;
//create directory if not exists
File pathDir = new File(base + path);
if (!pathDir.exists()) {
pathDir.mkdirs();
}
//download file
try {
OutputStream output = new FileOutputStream(base + path + file);
this._ftp.retrieveFile(file, output);
output.close();
} catch (Exception e) {
outcome = false;
} finally {
this._working = false;
return outcome;
}
}
// Connect to the server
protected boolean _connect() {
try {
this._ftp.connect(this._host);
this._ftp.login(this._user, this._pass);
} catch (Exception e) {
return false;
}
return this._ftp.isConnected();
}
// Disconnect from the server
protected void _disconnect() {
try {
this._ftp.disconnect();
} catch (Exception e) { /* do nothing */ }
}
}
I want to be able to call Worker.download(...) for each task in a queue whenever a worker becomes available without having to create a new connection to the ftp server for each download.
Any help would be appreciated as I've never used threads before and I'm going round in circles at the moment.
the examples have been setup to use a new Worker instance for each job, i want persistent workers.
This is a common question with a couple of different solutions. What you want is some context per thread as opposed to per Runnable or Callable that would be submitting to an ExecutorService.
One option would be to have a ThreadLocal which would create your ftp instances. This is not optimal because there would be no easy way to shutdown the ftp connection when the thread is terminated. You would then limit the number of connections by limiting the number of threads running in your thread-pool.
I think a better solution would be to use the ExecutorService only to fork your worker threads. For each worker, inject into them a BlockingQueue that they all use to dequeue and perform the tasks they need to do. This is separate from the queue used internally by the ExecutorService. You would then add the tasks to your queue and not to the ExecutorService itself.
private static final BlockingQueue<FtpTask> taskQueue
= new ArrayBlockingQueue<FtpTask>();
So your task object would have something like:
public static class FtpTask {
String base;
String path;
String file;
}
Then the run() method in your Worker class would do something like:
public void run() {
// make our permanent ftp instance
this._ftp = new FTPClient();
// connect it for the life of this thread
this._connect();
try {
// loop getting tasks until we are interrupted
// could also use volatile boolean !shutdown
while (!Thread.currentThread().isInterrupted()) {
FtpTask task = taskQueue.take();
// if you are using a poison pill
if (task == SHUTDOWN_TASK) {
break;
}
// do the download here
download(task.base, task.path, task.file);
}
} finally {
this._disconnect();
}
}
Again, you limit the number of connections by limiting the number of threads running in your thread-pool.
What i ideally want to do is have a single connection for scanning directories and building up a file list then four workers to download said files.
I would have a Executors.newFixedThreadPool(5); and add one thread which does the scanning/building and 4 worker threads that are doing the downloading. The scanning thread would be putting to the BlockingQueue while the worker threads are taking from the same queue.
I would suggest go for ThreadPoolexecutor with core size and maxpoolsize as per requirements. Also use a Linked Blocking queue in this case which will act your tasks in it in a FIFO manner.
As soon as a Thread(worker) becomes free the task will be picked from queue and executed.
Check out details of ThreadPoolExecutor. Let me know in case you get stuck anywhere in implementation of ThreadPoolexecutor.
Motivation for this question
I am running a huge product that runs on very expensive hardware. Shutting it down for testing purpose is not possible, nor is putting up a bad jar on production environment. I need to be as sure as possible to almost ensure that I don't mess up the production environment.
I need the below code reviewed for obvious issues before I run this on the staging setup (which is as expensive).
Problem
I have a socket based application, sometimes the clients dont send a CloseConnection request explicitly. And sometimes the IOException does not occur, there by holding up the threads on the blocking readObject call.
I need to close free this thread by closing the connection after a time out. If I get a new request from the server the timeout is refreshed.
So you will see 3 parts below
initializing
the readObject call in a while(true) loop, and the scheduled service reset
the actual closing of the instream
Code
I have been advised to use ScheduledExecutorService instead of Timer/TimerTask.
class StreamManager {
....
private ScheduledExecutorService activityTimeOut = Executors
.newSingleThreadScheduledExecutor();
private CloseConnectionOnTimeOut closeOnTimeOut = new CloseConnectionOnTimeOut();
....
public void initialize(Socket newClientSocket, ObjectInputStream newInputStream,
ObjectOutputStream newOutputStream, ThreadMonitor newThreadMonitor) {
....
closeOnTimeOut.setInputStream(myInputStream);
activityTimeOut.scheduleAtFixedRate(closeOnTimeOut, 0, Globals.INACTIVITY_TIME_OUT,
TimeUnit.MILLISECONDS);
}
public void run() {
....
while (true) {
try {
AMessageStrategy incomingCommand = (AMessageStrategy) myInputStream
.readObject();
activityTimeOut.shutdown();
activityTimeOut.scheduleAtFixedRate(closeOnTimeOut, 0,
Globals.INACTIVITY_TIME_OUT, TimeUnit.MILLISECONDS);
....
}
....
}
class CloseConnectionOnTimeOut implements Runnable {
private ObjectInputStream myInputStream;
public CloseConnectionOnTimeOut() {
}
public void setInputStream(ObjectInputStream myInputStream) {
this.myInputStream = myInputStream;
}
public void run() {
try {
myInputStream.close();
myOutputStream.close();
clientSocket.close();
log.info("Time out occured for client, closed connection forcefully.") ;
} catch (IOException e) {
e.printStackTrace();
log.fatal("Time out has occured, yet unable to clean up client connection. Keep a watch out on \"Size of clientStreamQ\"");
}
}
}
Edit :
Just tested a smaller application, and it seems to work. I still need your feedback.
Edit Again :
I have modified the code below as per advice.
Initializing
private ScheduledExecutorService activityTimeOut = Executors
.newSingleThreadScheduledExecutor();
private Future<Void> timeoutTask ;
private CloseConnectionOnTimeOut closeOnTimeOut = new CloseConnectionOnTimeOut();
Removed this code
closeOnTimeOut.setInputStream(myInputStream);
activityTimeOut.scheduleAtFixedRate(closeOnTimeOut, 0, Globals.INACTIVITY_TIME_OUT,
TimeUnit.MILLISECONDS);
Replaced before and after readObject
timeoutTask = (Future<Void>) activityTimeOut.scheduleAtFixedRate(
closeOnTimeOut.setInputStream(myInputStream), 0,
Globals.INACTIVITY_TIME_OUT, TimeUnit.MILLISECONDS);
AMessageStrategy incomingCommand = (AMessageStrategy) myInputStream
.readObject();
timeoutTask.cancel(true) ;
On Cleanup
activityTimeOut.shutdown() ;
You cannot submit tasks to an ExecutorService that was already shut down. If you want to stop a task executing, cancel it. Besides that, your cancel task will be scheduled to run as soon as the StreamManager is initialized - if there is a gap between initialize and run you could get into trouble. I would suggest to create and schedule a new task right before attempting to read from the socket, and cancel it after the read succeeded:
while (true) {
...
Future<Void> timeoutTask = activityTimeOut.schedule(new CloseConnection(/*init with streams*/), Globals.INACTIVITY_TIME_OUT, TimeUnit.MILLISECONDS);
try {
AMessageStrategy incomingCommand = (AMessageStrategy) myInputStream.readObject();
} finally {
timeoutTask.cancel(false);
}
...
}
In a clean up method of the StreamManager or at the end of run() you should shutdown the used ScheduledExecutorService.
If your software is mission critical I would thoroughly test it locally. Write unit tests and perhaps small integration tests to verify that the cancelling works. But I'm afraid that this solution is rather brittle. Multi-threading and IO add a lot of uncertainties.
I have created a threaded service the following way:
public class TCPClientService extends Service{
...
#Override
public void onCreate() {
...
Measurements = new LinkedList<String>();
enableDataSending();
}
#Override
public IBinder onBind(Intent intent) {
//TODO: Replace with service binding implementation
return null;
}
#Override
public void onLowMemory() {
Measurements.clear();
super.onLowMemory();
}
#Override
public void onDestroy() {
Measurements.clear();
super.onDestroy();
try {
SendDataThread.stop();
} catch(Exception e){
...
}
}
private Runnable backgrounSendData = new Runnable() {
public void run() {
doSendData();
}
};
private void enableDataSending() {
SendDataThread = new Thread(null, backgrounSendData, "send_data");
SendDataThread.start();
}
private void addMeasurementToQueue() {
if(Measurements.size() <= 100) {
String measurement = packData();
Measurements.add(measurement);
}
}
private void doSendData() {
while(true) {
try {
if(Measurements.isEmpty()) {
Thread.sleep(1000);
continue;
}
//Log.d("TCP", "C: Connecting...");
Socket socket = new Socket();
socket.setTcpNoDelay(true);
socket.connect(new InetSocketAddress(serverAddress, portNumber), 3000);
//socket.connect(new InetSocketAddress(serverAddress, portNumber));
if(!socket.isConnected()) {
throw new Exception("Server Unavailable!");
}
try {
//Log.d("TCP", "C: Sending: '" + message + "'");
PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
String message = Measurements.remove();
out.println(message);
Thread.sleep(200);
Log.d("TCP", "C: Sent.");
Log.d("TCP", "C: Done.");
connectionAvailable = true;
} catch(Exception e) {
Log.e("TCP", "S: Error", e);
connectionAvailable = false;
} finally {
socket.close();
announceNetworkAvailability(connectionAvailable);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
connectionAvailable = false;
announceNetworkAvailability(connectionAvailable);
}
}
}
...
}
After I close the application the phone works really slow and I guess it is due to thread termination failure.
Does anyone know what is the best way to terminate all threads before terminating the application?
Addendum: The Android framework provides many helpers for one-off work, background work, etc, which may be preferable over trying to roll your own thread in many instances. As mentioned in a below post, AsyncTask is a good starting point to look into. I encourage readers to look into the framework provisions first before even beginning to think about doing their own threading.
There are several problems in the code sample you posted I will address in order:
1) Thread.stop() has been deprecated for quite some time now, as it can leave dependent variables in inconsistent states in some circumstances. See this Sun answer page for more details (Edit: that link is now dead, see this page for why not to use Thread.stop()). A preferred method of stopping and starting a thread is as follows (assuming your thread will run somewhat indefinitely):
private volatile Thread runner;
public synchronized void startThread(){
if(runner == null){
runner = new Thread(this);
runner.start();
}
}
public synchronized void stopThread(){
if(runner != null){
Thread moribund = runner;
runner = null;
moribund.interrupt();
}
}
public void run(){
while(Thread.currentThread() == runner){
//do stuff which can be interrupted if necessary
}
}
This is just one example of how to stop a thread, but the takeaway is that you are responsible for exiting a thread just as you would any other method. Maintain a method of cross thread communcation (in this case a volatile variable, could also be through a mutex, etc) and within your thread logic, use that method of communication to check if you should early exit, cleanup, etc.
2) Your measurements list is accessed by multiple threads (the event thread and your user thread) at the same time without any synchronization. It looks like you don't have to roll your own synchronization, you can use a BlockingQueue.
3) You are creating a new Socket every iteration of your sending Thread. This is a rather heavyweight operation, and only really make sense if you expect measurements to be extremely infrequent (say one an hour or less). Either you want a persistent socket that is not recreated every loop of the thread, or you want a one shot runnable you can 'fire and forget' which creates a socket, sends all relevant data, and finishes. (A quick note about using a persistent Socket, socket methods which block, such as reading, cannot be interrupted by Thread.interrupt(), and so when you want to stop the thread, you must close the socket as well as calling interrupt)
4) There is little point in throwing your own exceptions from within a Thread unless you expect to catch it somewhere else. A better solution is to log the error and if it is irrecoverable, stop the thread. A thread can stop itself with code like (in the same context as above):
public void run(){
while(Thread.currentThread() == runner){
//do stuff which can be interrupted if necessary
if(/*fatal error*/){
stopThread();
return; //optional in this case since the loop will exit anyways
}
}
}
Finally, if you want to be sure a thread exits with the rest of your application, no matter what, a good technique is to call Thread.setDaemon(true) after creation and before you start the thread. This flags the thread as a daemon thread, meaning the VM will ensure that it is automatically destroyed if there are no non-daemon threads running (such as if your app quits).
Obeying best practices with regards to Threads should ensure that your app doesn't hang or slow down the phone, though they can be quite complex :)
Actually, you don't need the "runner" variable as described above, something like:
while (!interrupted()) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
break;
}
}
But generally, sitting in a Thread.sleep() loop is a really bad idea.
Look at the AsyncTask API in the new 1.5 API. It will probably solve your problem more elegantly than using a service. Your phone is getting slow because the service never shuts down - there's nothing that will cause the service to kill itself.