Java EE scheduled task and forced task - multithreading

I'm working on a Java EE Web application.
I've developed a Scheduled Batch using #WebListener annotation:
#WebListener
public class BatchServlet implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
context = sce.getServletContext();
schedulerEngine = Executors.newSingleThreadScheduledExecutor();
schedulerEngine.scheduleAtFixedRate(new MyThread(), 0, 300, TimeUnit.SECONDS);
}
public class MyThread implements Runnable {
#Override
public void run() {
...... //my business logic
}
and it works correctly.
But, for my purpose, I need to force the MyThread() batch on demand, for example, when I received a particular request within a Servlet. Obviosly I can call the MyBatch thread separately, but I was wondering that there are some best practices to perform this operation.

There are a couple of options: create a regular thread pool (with multiple threads) and just put tasks on the executor queue whenever they come in.
If you need more fine-grained control, you can share something like a concurrent queue between the servlet and the one thread that you have. Let this thread read from the queue, it will block automatically when the queue is empty.
Then your servlet can put work on this queue, if the thread happened to be blocked on getting an item it will automatically wake up.
You might wanna look up the "producer-consumer" pattern. There is a lot of literature about this.

Related

Run java function in thread

Is there way to run function/method in its own thread?
I have two use cases for this right now. One is that I have a Consumer<T> that is passed in. I want to run this on its own thread as it will take a long time to finish.
The other use case that I have is that I have a number of functions in the same class that I want to run in their own threads individually (one thread per function). These functions need access to private data in their class's state.
Is there a way to do this in java?
Update: For what its worth, I know about the "normal" way of doing this, either by extending Thread, or implementing runnable. However, in both of these cases those approaches don't work.
Update 2:
Implementing Runnable won't work as the class has a number of different methods that all have to be independently "run" on their own threads. Given that there are quite a few methods in this class that would need to run threads, this won't work. Since these threads require access to some shared private data, I can't even split each method into its own class (even though that would not map to what I would consider a logical class anyway).
For the case where I have a Consumer<T> I can't extend/implement Thread/Runnable as I don't control the interface. The method takes a Consumer<T> as a parameter, and I need to call it in it's own thread. I suppose here I could create a wrapper class, but then I would have to create (I think) one wrapper class each for Consumer, Function, etc. And all of this seems rather needless (at least coming from other languages).
Update 3: Assume that synchronization is not an issue (data is either immutable, or contention is very low)
I am looking for a better way. Is this clearer?
As a partial solution for the functions / methods (if they don't need arguments) you can use Threads or an ExecutorService and method references.
If you need arguments you will have to write lambda expressions - see the method t3 and it's start for an example.
public class Test {
public void t1() {
System.out.println("t1");
}
public void t2() {
System.out.println("t2");
}
public void t3(int n) {
System.out.println("t3:"+n);
}
public static void main(String[] args) throws InterruptedException {
Test test = new Test();
Thread t = new Thread(test::t1);
t.start();
ExecutorService es = Executors.newFixedThreadPool(5);
es.submit(test::t2);
es.submit(() -> test.t3(99));
es.shutdown();
es.awaitTermination(1, TimeUnit.SECONDS);
}
}

How does start() method invoke threads in Java?

With an example code shown to create a thread by invoking start() method of java.lang.Thread class,
public class MyThread extends Thread{
public void run(){
//code to run goes here
}
}
MyThread myThread = new MyThread();
myThread.start();
I understand that a second thread gets created in addition to main thread. This second thread performs the work given in run() method.
So, the JVM process is running this code with two user level threads.
Sun J2SE 5.0 is the environment running on Windows 2008/2012 boxes.
My question:
How many kernel level threads does OS dedicate for this JVM process? Does each user level thread map to a separate kernel thread? It is important to know this info, before running the enterprise application with configurable number of threads on destination OS platform.

Spring #Async limit number of threads

My question is very similar to this one : #Async prevent a thread to continue until other thread have finished
Basically i need run ~ hundreds of computations in more threads. I want to run only some amount of parallel threads e.g. 5 threads with 5 computationis in paralell.
I am using spring framework and #Async option is natural choice. I do not need full-featured JMS queue, that`s a bit overhead for me.
Any ideas ?
Thank you
If you are using Spring's Java-configuration, your config class needs to implements AsyncConfigurer:
#Configuration
#EnableAsync
public class AppConfig implements AsyncConfigurer {
[...]
#Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(5);
executor.setQueueCapacity(50);
executor.setThreadNamePrefix("MyExecutor-");
executor.initialize();
return executor;
}
}
See #EnableAsync documentation for more details : http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html
Have you checked out Task Executor? You can define a Thread Pool, with a maximum number of threads to execute your tasks.
If you want to use it with #Async, use this in your spring-config:
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>
Full reference here (25.5.3). Hope this helps.
Since spring boot 2.1 you can use auto configuration and change the maximum number of threads in the application properties file
spring.task.execution.pool.max-size=4
See the full documentation:
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-task-execution-scheduling

Multiple Threads starting a Transaction within JUNIT

I am trying to reproduce (and not fullproof test the multithreading issue) the thread block issue in one of my methods by writing a unit test. Since I see plenty of instances of
org.hibernate.exception.LockAcquisitionException: could not execute update query
in our 2 server PROD environment, I should be able to reproduce fairly easily in my unit test.
I tried to spawn multiple threads within my JUnit method and each thread invoking my method. I tried with 2 threads to begin with.
ExecutorService exec = Executors.newFixedThreadPool(16);
for (int i = 0; i < 2; i++) {
exec.execute(new Runnable() {
public void run() {
System.out.println("who is running: " + Thread.currentThread().getId());
em.getTransaction().begin();
//do something()
em.getTransaction().commit();
}
});
}
I get an error:
Exception in thread "pool-1-thread-2" who is running: 11
java.lang.IllegalStateException: Transaction already active
at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:35)
It is not letting me create Transaction for the second thread with an error 'Transaction is already Active'. I thought EntityManager could have multiple Active Threads present at any given time ( and hence a singleton entitymanager)?
Am I missing something here?
Thanks
EntityManager is not thread-safe. That's why it is often told that you should not inject EntityManager to shared instances like Servlets. It is clearly documented (JSR-317 page 286):
An entity manager must not be shared among multiple concurrently
executing threads, as the entity manager and persistence context are
not required to be threadsafe. Entity managers must only be accessed
in a single-threaded manner.

Invoking time-consuming JNI task as a thread

I'm having a tough problem with invoking a native function using JNI from a thread.
The native function is legacy code that performs a computation-intensive task. Since I'd like not to freeze the rest of the program, the computation should be performed in a background thread. EventBus is used to send the calculation result back to the main program.
Basically it should be quite simple, something like this:
public class CalculationEngine {
private CalculationEngine(){}
public static void calculateInBackground(final Parameters parameters) {
new Thread(new Runnable() {
public void run() {
// Someone might change the parameters while our thread is running, so:
final Parameters clonedParameters = parameters.clone();
Results results = new Results();
natCalc(clonedParameters, results);
EventBus.publish("Results", results);
}
}).start();
}
public static void calculateNormally(final Parameters parameters) {
Results results = new Results();
natCalc(parameters, results);
EventBus.publish("Results", results);
}
private static native synchronized void
natCalc(Parameters parameters, Results results);
}
Now, the calculateNormally method, which blocks the main program, works fine, but the calculateInBackground method, which just constructs a background thread to do the same thing, causes various crashes in the native code when it's invoked consecutively. By consecutively I mean that it's called again only after the previous thread has finished and returned the result. Note that the native code is marked synchronized to ensure that only one instance of it can be running at a time.
My question is, how on earth can the native code behave differently depending on whether it's invoked from the main thread, or from some other thread? It's like the native code were keeping "state", and not really quitting, when it's called from within a thread other than the main thread. Is there a way to "clean" or "flush" a thread after it's finished? There must be something in JNI & Threads that I simply don't know.
Thanks for any hints!
I figured out a working solution, after googling and finding the phrase "I've found JNI to be very buggy when called from seperate threads... So make sure only one thread ever calls your native code!". It seems to be true; the solution is to keep a persistent, "reusable" thread around - I used Executors.newSingleThreadExecutor() - and to call the native code only from that thread. It works.
So the difference from JNI point of view was not between main thread vs. some other thread, but in using different threads in consecutive calls. Note that in the problematic code a new thread was constructed each time. It should work that way, but it doesn't. (And no, I'm not caching JNIEnv pointer.)
Whether it's a JNI bug, bug in the native code, something in the interaction between them and OS or whatever, would be interesting to know. But sometimes you just have no chance to debug 10000+ lines of existing code in detail, however, you're happy to get it to work. Here's working version of the example code, let's call this a workaround:
public class CalculationEngine {
private CalculationEngine(){}
private static Parameters parameters;
private static ExecutorService executor = Executors.newSingleThreadExecutor();
private static Runnable analysis = new Runnable() {
public synchronized void run() {
Results results = new Results();
natCalc(parameters, results);
EventBus.publish("Results", results);
}
};
public static synchronized void
calculateInBackground(final Parameters parameters) {
CalculationEngine.parameters = parameters.clone();
executor.submit(analysis);
}
private static native synchronized void
natCalc(Parameters parameters, Results results);
}
My advice on using JNI is DON'T if you can possibly avoid it. The chances are that it will cause stability issues for you. Here are some possible alternatives:
Recode the native library in Java.
Write a wrapper command for the native library in C / C++ / whatever and run it using java.lang.Process and friends
Turn the native library into a daemon and access it using Sockets.
While you've got an answer, I don't think too much has been provided as to possible root cause. Here's a few possibilities, but there are others. Note, these apply to Windows.
There's an apartment threaded COM object involved. Apartment threaded COM objects, which are the only type VB can create, can only be used on the thread that creates them.
Security features, like impersonation, are often thread isolated. If the initialization code modified the context of the thread, future calls that expect the context to be in place will fail.
Thread specific memory storage is a technique within some applications to support multi-threadedness (Java also has such a feature).
Here there is a good documentation about it: Section 8.1 JNI and Threads.
http://java.sun.com/docs/books/jni/download/jni.pdf

Resources