I'm using the ServletContextListener to create a new thread.
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.concurrent.*;
public class Port implements ServletContextListener {
private ExecutorService executor;
public void contextDestroyed(ServletContextEvent event) {
executor.shutdown();
}
public void contextInitialized(ServletContextEvent event) {
// start task
executor = Executors.newSingleThreadExecutor();
executor.submit(new Task()); //task should implement Runnable!
}
}
Inside this thread I'm reading data from a serial port (SerialPortEventListener). The task.class should read out information from the serial port during the whole period in which the server is active. I've thrown this inside a thread because there can only be one instance that reads from the serial port; data should then be shared to all clients.
Now I would like to acces the data this thread is reading from the serial port.
Can this be done? And if yes then how?
You could, for example, store the read data in a servlet context attribute. Then, from the other classes, you would get the attribute from the servlet context:
public void contextInitialized(final ServletContextEvent event) {
// start task
executor = Executors.newSingleThreadExecutor();
executor.submit(new Runnable() {
#Override
public void run() {
String data = readFromPort();
event.getServletContext().setAttribute("serialPortData", data);
}
});
}
}
Yes it can be done, and you have few options:
1- Using a shared concurrent.BlockingQueue where inside the thread add new data from the SerialPort and in your servlet read from that queue
2- Have an event listener object inside your servlet and pass it in your task constructor. The listener object should have a callback function that is invoked when SerialEvent occur.
In general, this is a typical producer/consumer pattern
You'll need to share the data in the new Runnable you're going to create. You can add to it a concurrent collection.
Related
I have a number of Runnable tasks governed by an executor service.
These tasks are essentially JMS queue pollers and contain their own connections.
For example:
ExecutorService executor = Executors.newFixedThreadPool(...);
executor.submit(new MyListener());
My listener:
public class MyListener implements Runnable {
#Override
public void run() {
// Create my JMS connection here
}
}
How do I gracefully close the JMS connection in each task and then proceed to shutdown each thread?
I'm having problems shutting down the executor service with shutdown().
I need to force an interrupt with shutdownNow(), however, how can I be sure that my JMS connection has been closed without me explicitly calling .close()?
Is there an interface I'm missing that allows shutdown hooks to be executed when I attempt to stop the task?
Here's my solution to gracefully shutdown threads holding a connection, utilising the suggestion of an atomic boolean:
MyRunnable implements Runnable {
private volatile boolean isActive = true;
public void run() {
while(isActive && !Thread.currentThread().isInterrupted()) {
...
}
}
public void stop() {
isActive = false;
}
}
Main thread:
private void myShutdownHook() {
myRunnableInstance.stop();
// Can safely shutdown executor now...
}
The easiest would be to use an atomic boolean shared by the class that signals shutdown and the runnable. This tells them to stop. Another option is finding the threads yourself and interrupt them. You would need to catch the interrupted exception and close the connection. You can set the thread names when the runnable launch for easy id.
I have a ExecutorService executor = Executors.newSingleThreadExecutor(); that i want to stop when the server is shutting down.
I have a class that implements ServletContextListener and it's annotated with #WebListener.
I have the two methods in that class:
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContextListener started");
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
executor.shutdown();
executor.shutdownNow();
System.out.println("ServletContextListener destroyed");
}
And I see that it prints what's in both of them when it's supposed to, but when I press the stop button once in intelij, I get:
SEVERE: The web application [] appears to have started a thread named [pool-2-thread-1] but has failed to stop it. This is very likely to create a memory leak.
Right after it printed ServletContextListener destroyed.
I need to press the stop button again to fully stop it.
Why it doesn't shutdown the ExecutorService even though it reached the executor.shutdown();? What am I doing wrong?
PS: this is the only ExecutorService I have and no other threads are made by me.
EDIT2:
The executor service is a field in a singleton class, it's initialized with the class:
private ExecutorService executor = Executors.newSingleThreadExecutor();
This is how the class is initialized (lazy initialization):
public static RoomsManager getRoomsManager(ServletContext servletContext) {
if (servletContext.getAttribute(MANAGER_GAMES_ATTRIBUTE_NAME) == null) {
servletContext.setAttribute(MANAGER_GAMES_ATTRIBUTE_NAME, new RoomsManager());
}
return (RoomsManager)servletContext.getAttribute(MANAGER_GAMES_ATTRIBUTE_NAME);
}
And is annotated like this:
#WebListener
public class RoomsManager implements ServletContextListener {
The stop button is the red square near the play and debug buttons in intelij IDEA.
The problem is that you have two different RoomsManager instances (and hence, two different executors): first is created by Tomcat, and second is created by you.
When you annotate RoomsManager with #WebListener, Tomcat automatically creates an instance of that class and subscribes it to receive servlet context create/destroy events. That instance is the one that actually stops its executor and prints ServletContextListener destroyed.
The second instance is created by you in the getRoomsManager method (by the way, that method doesn't look thread-safe). That instance is not registered with Tomcat and doesn't receive servlet context "destroy" event, so it doesn't even try to shutdown its executor.
Doing this worked:
class YourThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
return new Thread(r, "Your name");
}
}
private ExecutorService executor = Executors.newSingleThreadExecutor(new YourThreadFactory());
Because apparently, the threads of tomcat are daemons, and therefore, when they create a new thread with return new Thread(r, "Your name"); it also becomes a daemon.
But in the DefaultThreadFactory that an executor service use, I saw that it makes sure daemonity of new threads is off.
That doesn't explain why executor.shutdown(); didn't work though, but now at least it properly shuts down.
I'm using ListenableFuture from Guava, and one nice thing about them is that one pass Executor to the Futures.addCallback method, that is, ask to execute the callback on a given thread/executor.
In my Android application, I want to be able to start the asynchronous execution based on ListenableFuture in the UI thread, and schedule a callback which is also executed also on the UI thread. Therefore, I'd like to somehow submit the UI thread executor to the Futures.addCallback method mentioned above. How to achieve that?
Or, in other words, I want to have an executor for the UI thread. Is it available already in Android, or, if I have to create my own, how do I do that?
EDIT: As an extension to this question, is it possible to do same thing, but not just with UI thread, but with any particular thread, where the call to async method is made?
I would be happy to know how to achieve the same effect without resorting to the Android-specific stuff like Handler and Looper, just with pure Java.
I think I've see some implementation doing that. The basic Idea is roughly
class UiThreadExecutor implements Executor {
private final Handler mHandler = new Handler(Looper.getMainLooper());
#Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
You can delegate to run anything in the main thread by passing it to a handler for the main thread.
Edit: https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit/android/MainThreadExecutor.java for example
Edit2: You can configure the handler like e.g. SensorManager#registerListener(..., Handler handler) allows you to do.
class HandlerThreadExecutor implements Executor {
private final Handler mHandler;
public HandlerThreadExecutor(Handler optionalHandler) {
mHandler = optionalHandler != null ? optionalHandler : new Handler(Looper.getMainLooper());
}
#Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
The advantage over using the current thread's looper is that it makes it explicit which Looper you use. In your solution you take the Looper of whatever thread calls new ExecuteOnCaller() - and that's often not the thread you run code in later.
I would be happy to know how to achieve the same effect without resorting to the Android-specific stuff like Handler and Looper, just with pure Java.
Looper, Handler and the message queue behind all that logic are made of mostly pure Java. The problem with a generic solution is that you can't "inject" code to run into a thread. The thread must periodically check some kind of task queue to see if there is something to run.
If you write code like
new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("Hello");
}
}
}).start();
Then there is no way to make that thread do anything else but constantly print "Hello". If you could do that it would be like dynamically inserting a jump to other code into the program code. That would IMO be a terrible idea.
final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
Runnable codeToRunInThisThread = queue.take();
codeToRunInThisThread.run();
}
} catch (InterruptedException ignored) {}
}
}).start();
On the other hand is a simple thread that loops forever on a queue. The thread could do other tasks in between but you have to add a manual check into the code.
And you can send it tasks via
queue.put(new Runnable() {
#Override
public void run() {
System.out.println("Hello!");
}
});
There is no special handler defined here but that's the core of what Handler & Looper do in Android. Handler in Android allows you to define a callback for a Message instead of just a Runnable.
Executors.newCachedThreadPool() and similar do roughly the same thing. There are just multiple threads waiting on code in a single queue.
As an extension to this question, is it possible to do same thing, but not just with UI thread, but with any particular thread, where the call to async method is made?
The generic answer is No. Only if there is a way to inject code to run in that thread.
Based on asnwer from #zapl, here is my implementation, which also answers the edited (extended) question: https://gist.github.com/RomanIakovlev/8540439
Figured out I'll also put it here, in case if link will rot some day:
package com.example.concurrent;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Executor;
/**
* When the calling thread has a Looper installed (like the UI thread), an instance of ExecuteOnCaller will submit
* Runnables into the caller thread. Otherwise it will submit the Runnables to the UI thread.
*/
public class ExecuteOnCaller implements Executor {
private static ThreadLocal<Handler> threadLocalHandler = new ThreadLocal<Handler>() {
#Override
protected Handler initialValue() {
Looper looper = Looper.myLooper();
if (looper == null)
looper = Looper.getMainLooper();
return new Handler(looper);
}
};
private final Handler handler = threadLocalHandler.get();
#Override
public void execute(Runnable command) {
handler.post(command);
}
}
My pattern to use it would be like this:
/**
* in SomeActivity.java or SomeFragment.java
*/
Futures.addCallback(myModel.asyncOperation(param), new FutureCallback<Void>() {
#Override
public void onSuccess(Void aVoid) {
// handle success
}
#Override
public void onFailure(Throwable throwable) {
// handle exception
}
}, new ExecuteOnCaller());
Use com.google.android.gms.tasks.TaskExecutors.MAIN_THREAD.
An Executor that uses the main application thread.
Source: Android docs
The tasks APIs are part of Google Play services since version 9.0.0.
For Android UI thread executor use:
ContextCompat.getMainExecutor(context)
To address your question and extended question to create an Executor that simply runs on the current thread and avoids Android classes:
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
See documentation: https://developer.android.com/reference/java/util/concurrent/Executor
Using Guava's EventBus, I want to be able to post from a background thread (called "background") to a specific thread (in this case, thread "main") that updates the UI. I thought the following would work, but this calls the subscriber code from the background thread:
package com.example;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.common.util.concurrent.MoreExecutors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EventBusTester {
private static final Logger log = LoggerFactory.getLogger(EventBusTester.class);
public static void main(String... args) {
new EventBusTester().run();
}
private void run() {
log.info("Starting on thread {}.", Thread.currentThread().getName());
final EventBus eventBus = new AsyncEventBus(MoreExecutors.sameThreadExecutor());
eventBus.register(this);
Thread background = new Thread(new Runnable() {
#Override
public void run() {
long now = System.currentTimeMillis();
eventBus.post(now);
log.info("Posted {} to UI on thread {}.", now, Thread.currentThread().getName());
}
}, "background");
background.start();
}
#Subscribe
public void updateUi(Long timestamp) {
log.info("Received {} on UI on thread {}.", timestamp, Thread.currentThread().getName());
}
}
This prints the following:
02:20:43.519 [main] INFO com.example.EventBusTester - Starting on thread main.
02:20:43.680 [background] INFO com.example.EventBusTester - Received 1387848043678 on UI on thread background.
02:20:43.680 [background] INFO com.example.EventBusTester - Posted 1387848043678 to UI on thread background.
So my questions are:
Is it possible to do what I want, e.g. with an ExecutorService I've somehow missed, or writing a custom ExecutorService, or
Do I need some other library to accomplish this? E.g. Square's Otto (because I'll be using this on Android as well).
I'd rather stay with pure Guava, though.
Thanks!
If you use an EventBus instance then the #Subscribe method will be executed on the same thread that posted the event.
If you want to do something different then use an AsyncEventBus where you can provide an Executor to define the exact behavior in case of an event gets posted.
For instance, on Android to make every #Subscribe method run on the main thread you can do the following:
EventBus eventBus = new AsyncEventBus(new Executor() {
private Handler mHandler;
#Override
public void execute(Runnable command) {
if (mHandler == null) {
mHandler = new Handler(Looper.getMainLooper());
}
mHandler.post(command);
}
});
The Looper.getMainLooper() returns the application's main looper, which lives on the main thread of the application.
In UI applications, there is a thread running an event dispatch loop. which is processing user input events and calling handlers. Typically, UI framework provides some way to execute your code in this thread, like SwingUtilities.invokeLater(Runnable)
AsyncEventBus allows you to pass pass Executor, which will be calling UI-framework specific function for that.
There are a few questions here related to executing UI code from a worker thread on android.
I'm developing a web application to be deployed onto Tomcat. When Tomcat is started, I use a servlet (in web.xml) to call a Java class:
<web-app>
<display-name>Consumer</display-name>
<servlet>
<servlet-name>start</servlet-name>
<servlet-class>com.test.sample.Consumer</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
</web-app>
My Consumer.java subscribes to a queue on an AMQP server. I achieve this by using a while (true) loop, which works fine in a standalone Java program. Itt also works in the context of the web application, but I can never stop my Tomcat server (within my NetBeans IDE), and I believe that the while loop is the culprit. Here is some code:
public class Consumer {
public Consumer()
consume();
}
private void consume()
...
while (true) {
// Await incoming messages from queue
// Process message
}
}
}
Is there a better way to handle this? Or to signal a stop to break out of the loop?
Thanks!
Updated to use ServletContextListener:
public final class ApplicationListener implements ServletContextListener {
private ScheduledExecutorService scheduler;
public ApplicationListener() {
}
#Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("***** Stopping Consumer *****");
scheduler.shutdownNow();
}
#Override
public void contextInitialized(ServletContextEvent event) {
System.out.println("***** Starting Consumer *****");
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new ScheduledConsumer(), 0, 15000, TimeUnit.MILLISECONDS);
}
public class ScheduledConsumer implements Runnable {
#Override
public void run() {
Consumer k = new Consumer();
k.consumeOnce();
}
}
}
I have some suggestions, but they require that you modify your architecture a bit in order to more nicely play with your container environment.
Servlet containers support "listeners" that can get notification of various events. Specifically, one of them is the ServletContextListener which gets notified when the context (aka. webapp) is being brought into service (via the contextInitialized method) and when it is being brought out of service (via the contextDestroyed method).
My recommendation would be to do the following:
Change your Consumer class's constructor so that it does not automatically call consume(); instead, add a public method like consumeOnce and don't use a loop at that level at all
Write a ServletContextListener that has a Consumer and a Thread reference as members as well as a volatile boolean stop flag; in contextInitialized it should create a new Consumer object, then launch a new (daemon) thread that:
Calls Consumer.consumeOnce
Calls Thread.sleep for an appropriate amount of time
Loops over the previous 2 steps until the stop flag is true
Have your ServletContextListener's contextDestroyed method set the stop flag to true and call Thread.interrupt on the running thread.
I'm sure I'm missing some exact details, but that's the general idea. When Tomcat shuts down, your code will be notified of the shutdown and you can cleanly terminate your own looping-thread. You may need to provide a way for the Consumer to abort an attempt to consume whatever it consumes (e.g. stop waiting to pull an object from an empty queue) if it doesn't abort when it gets a Thread.interrupt signal. (For instance if you use an Object.wait() in order to wait for a monitor notification, then you'll want to change that so it uses a wait with a timeout so that you won't block forever).
You have to place the code with the loop in a different thread and start the thread from your consumer.
private void consume() {
Thread x = new Thread(new Runnable() {
#Override
public void run() {
while(true) {
....
}
});
x.start();
}