Using Async multithreading in Spring to run concurrent tasks - java

I am very new to Spring and I am trying to call two methods from two separate classes a number of times, and I want each invocation to spin a new thread so they run concurrently. This is the code I have:
the main class:
#SpringBootApplication
#EnableOAuth2Client
#EnableAsync
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
class SomeOtherClass {
for (int i = 0; i < 100; i++) {
Class1 class1 = new Class1();
class1.method1(//its arguments);
}
// doing other things
// ...
// method 2 will use the side effects of method 1, so ideally this next
// for loop should start only after the previous one is over
for (int i = 0; i < 50; i++) {
Class2 class2 = new Class2();
class2.method2(//its arguments);
}
}
public Class1 {
#Async("threadPoolTaskExecutor")
public void method1() throws Exception {
LOGGER.info("Running this in {}", Thread.currentThread().getName());
}
}
public Class2 {
#Async("threadPoolTaskExecutor")
public void method2() throws Exception {
LOGGER.info("Running this in {}", Thread.currentThread().getName());
}
}
#Configuration
#EnableAsync
public class ThreadConfig {
#Bean("threadPoolTaskExecutor")
public TaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(100);
executor.setMaxPoolSize(100);
executor.initialize();
return executor;
}
}
The problem is when I run the application I only see one thread name printing, which means it's not running in a multithreaded way. Looking at the logs, I can also see the calls are being made sequentially. Having done multithreading using standard Java (Runnable), I know the multithreaded version should finish much faster. Since I am very new to Spring, I do not understand what I am doing wrong.
I have redacted the method names and logic, but the annotations and class structures are exactly thee same, so if you see any problem with that please point that out.

To get method1 and method2 work asynchronously you have to let Spring manage instances of the Class1 and Class2. Replace Class1 class1 = new Class1(); with the dependency injection.
#Service
public Class1 {
...
#Service
class SomeOtherClass {
#Autowired
Class1 class1;
//...
// your loops
EDIT:
If you need to perform second loop only after completion of all async executions in the first loop then you can use Future class:
#Async(...)
public Future<Object> method1() {
...
return null;
}
List<Future<Object>> futures = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
futures.add(class1.method1(/*its arguments*/));
}
futures.forEach(f -> {
try {
f.get();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
});
// all of invocations of method1 are finished

Related

Junit Mocking a async thread call

I am trying to unit test Class A, where Class A is as follows
Class A{
private final classB = new ClassB();
public Void test(ScheduledEvent scheduledEvent, Context context) {
try {
Thread thread2 = new Thread(() -> doHandleRequest());
thread2.start();
thread2.join(3000);
if (thread2.isAlive()) {
thread2.interrupt();
// sleep for 30 seconds to flush any logs or CFN metrics.
Thread.sleep(30000);
}
} catch (InterruptedException ex) {
}
}
void doHandleRequest() {
try {
classB.sweep();
} catch(Exception ex) {
log.error("Exception in SweepThread while sweeping and deleting lambdas", ex);
}
}
}
Class B{
public void sweep(){
// do something;
}
I want to unit test Class A scenario where thread2.isAlive() condition is true and it goes to that if block.
First, you need to change how you create ClassB object to allow mocking, it can not be done when objects get created every time.
You can do that like this
public class ClassA {
private final ClassB b;
// this will allow you to inject mock from outside, as it's final, can be initialized only via a constructor.
public ClassA(ClassB b){
this.b = b;
}
// your remaining code
}
And now, in your test case, you need to inject mocks.
#Test
public void test() throws InterruptedException {
ClassB classB = Mockito.mock(ClassB.class);
ClassA classA = new ClassA(classB);
MockitoAnnotations.initMocks(this); // this will initialize mocks
//above can be skipped if you are using annotations for the same
Mockito.stubVoid(classB)
.toAnswer(invocationOnMock -> {
Thread.sleep(4000);
return null;
}).on().sweeps();
parent.test(null, null);
}
To make sure, your thread is alive after join, you can add delay in mock method of classB.
As your method returns void, we need to use stubVoid, otherwise it will be like this.
Mockito.when(mock.method(/* args, if, any */)).thenAnswer(mock -> {
Thread.sleep(delayInMilliseconds);
return desiredValue;
})

Accessing a static method when initializing a static field of same class from another thread

I had a very peculiar problem happening to me that I could not solved except splitting up the Problem into two classes.
I would like to know if there is maybe a solution without splitting the class and I would more importantly like to know if anybody has an idea why the Java Engine is deciding to act the way it does.
The Problem:
I have a class with a static method, a static field and a constructor. The static field is initialized to an instance of the class itself. During the instance initialization I want to access the aformentioned static method. See the following code:
public class Simple {
public Simple() {
int count = 4;
for (int i = 0; i < count; i++) {
System.out.println("Simple: " + Simple.isFlag());
}
}
private static Simple i = new Simple();
public static boolean isFlag() {
return true;
}
public static void run() {
}
}
public class Main {
public static void main(String[] args) {
Simple.run();
}
}
This code runs absolutely fine. The output can be seen below:
Simple: true
Simple: true
Simple: true
Simple: true
The output is generated after I call the run() method because the stativ field i is only initialized after I access the first static member of that class.
I now want to do the exact same thing except with multiple threads. See here:
public class Parallel {
public Parallel() {
int count = 4;
CountDownLatch latch = new CountDownLatch(4);
for (int i = 0; i < count; i++) {
Thread t = new Thread(() -> {
System.out.println("Parallel: " + Parallel.isFlag());
latch.countDown();
Thread.currentThread().interrupt();
});
t.start();
}
try {
latch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static Parallel i = new Parallel();
public static boolean isFlag() {
return true;
}
public static void run() {
}
}
public class Main {
public static void main(String[] args) {
Parallel.run();
}
}
This returns nothing. The main thread is stuck at latch.await();, while the other threads are stuck at Parallel.isFlag(). Edit: as shown by Jaims below, the threads don't even start at all.
This does not make any sense to me. Why is this not working, but the first case is? Essentially they are doing the same.
I would like to know how the Java Engine decides on when to wait and when not. Can this be changed somewhere in code?
Additionally, this has nothing to do with CountDownLatch but solely with the multithreading. Look at this final sample:
public class NonParallel {
public NonParallel() {
int count = 4;
CountDownLatch latch = new CountDownLatch(4);
for (int i = 0; i < count; i++) {
System.out.println("NonParallel: " + NonParallel.isFlag());
latch.countDown();
}
try {
latch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static NonParallel i = new NonParallel();
public static boolean isFlag() {
return true;
}
public static void run() {
}
}
public class Main {
public static void main(String[] args) {
NonParallel.run();
}
}
This works fine. The output is as following:
NonParallel: true
NonParallel: true
NonParallel: true
NonParallel: true
Edit: none of this applies when the object initlization is not part of the class initilization. This is purely about class initialization which only happens when using a static object as described in this question. See here:
public class NonStaticParallel {
public NonStaticParallel() {
int count = 4;
CountDownLatch latch = new CountDownLatch(4);
for (int i = 0; i < count; i++) {
Thread t = new Thread(() -> {
System.out.println("NonStaticParallel: " + isFlag());
latch.countDown();
});
t.start();
}
try {
latch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static boolean isFlag() {
return true;
}
public static void run() {
new NonStaticParallel();
}
}
This one works without any issue:
Parallel: true
Parallel: true
Parallel: true
Parallel: true
Answers:
Andreas provides an explanation as to what is going on.
Jaims is right in that the threads do not even start at all. This probably happens because they need the class to be initialized and they are immediately therefore blocked. (If we use runnables that are in their own classes instead of lambda or anonymous inner classes then they run normally, unless of course they acess the any static members of the class being initialized)
Yoshi provides a link and an excerpt from the the spec, and is therefore marked as the right answer, as this is what I wanted.
I tried your code and did two things:
First, I made the lambda a static inner class of Parallel ... just in case; this didn't change anything.
Since you commented that the threads are stuck on Parallel.isFlag() I tried replacing the call with just true... and it worked!
So, I did a little research and I found this, which sounds like a promising explanation for what is going on: http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2
Specifically this part:
For each class or interface C, there is a unique initialization lock LC. The mapping from C to LC is left to the discretion of the Java Virtual Machine implementation. The procedure for initializing C is then as follows:
Synchronize on the initialization lock, LC, for C. This involves waiting until the current thread can acquire LC.
If the Class object for C indicates that initialization is in progress for C by some other thread, then release LC and block the current thread until informed that the in-progress initialization has completed, at which time repeat this step.
(Emphasis added.) So this would suggest the following:
Main thread started class initialization while evaluating private static Parallel i = new Parallel(); and started up the threads. Then it waited on latch.await(). Class object for Parallel should indicate that initialization is "in progress."
Started threads also try to reference a static member of Parallel. Each thread sees that initialization is in progress and decides to wait until the Main thread (which is now waiting on the threads to count down the latch) is done. Clearly this is a deadlock.
When you call run(), the current thread will begin class initialization. Any code referring to the class, e.g. call to isFlag() will also require class initialization.
In your Simple and NonParallel versions, the current thread is doing it all, and recursive class initialization is allowed (ignored actually), so isFlag() is executed, even though the class initialization is not yet complete.
In your Parallel version however, the call to isFlag() is done from another thread, and so that other thread has to wait for the class to be fully initialized. Since your constructor won't return until the threads run, and the threads can't run until the constructor returns and completes the class initialization, you have a deadlock.
Conclusion: You cannot perform class initialization code in parallel. Class initialization has to complete in a single thread.
You can start threads during class initialization if you want, but you cannot wait for them to complete (if they also access your class, and what would be the point of they didn't?).
Your threads are not started until the object is created correctly. Consider the following snippet:
public class Main {
public static void main(String[] args) {
Parallel.run();
}
}
class Parallel {
private static Parallel i = new Parallel();
public Parallel() {
try {
System.out.println("Inside constructor.");
for (int i = 0; i < 4; i++) {
Thread t = new Thread(() -> {
System.out.println("Running thread.");
});
System.out.println("Starting thread.");
t.start();
}
System.out.println("Sleeping 2 seconds.");
Thread.sleep(2000);
System.out.println("Leaving constructor.");
} catch (InterruptedException ex) {
Logger.getLogger(Parallel.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void run() {
}
}
It'll produce the following output:
Inside constructor.
Starting thread.
Starting thread.
Starting thread.
Starting thread.
Sleeping 2 seconds.
Leaving constructor.
Running thread.
Running thread.
Running thread.
Running thread.
The threads are started within the constructor 4 times, as the output shows. It starts sleeping for 2 seconds, leaves the constructor and then runs your threads. Not like it takes 2 seconds for your threads to run.
So the core issue with your problem, is that you're calling latch.await(), but your threads never get the chance to actually run. Meaning the latch isn't decremented and simply keeps waiting. You could move the logic to your run() method, but I'm not really sure what you're trying to achieve in the first place. e.g.
public static void run() {
int count = 4;
CountDownLatch latch = new CountDownLatch(4);
for (int i = 0; i < count; i++) {
Thread t = new Thread(() -> {
try {
Thread.sleep(2000);
latch.countDown();
} catch (InterruptedException ex) {
Logger.getLogger(Parallel.class.getName()).log(Level.SEVERE, null, ex);
}
});
System.out.println("Starting thread.");
t.start();
}
try {
System.out.println("Current count: " + latch.getCount());
latch.await();
System.out.println("Current count: " + latch.getCount());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

How to implement Runnable in Spring Framework for writing to a database

I am new to Spring and I wish to implement threads. I have tried the conventional Java run() method to send a database writing task to the thread. However, this causes a NullPointerException every time I am calling the database dao or service query within the run() method. If I place the query in the constructor then it works.
I think possibly I am not able to instantiate the dao/service variable in runnable?
public class TestThread implements Runnable{
#Autowired
public CarService carService;
public TestThread(List<Car> listcar) {
List<Car> listcar = new ArrayList<Car>();
//This works here
listcar = new java.util.ArrayList<Car>(carService.findAllServices(0, 10000));
for(int i=0;i<listcar.size();i++) {
System.out.println("The all car services in runnable constructor"+listcar.get(i).getName());
}
}
public void run() {
try {
runrun();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//This does not work
public void runrun() throws Exception {
List<Car> listcar = new ArrayList<Car>();
listcar = new java.util.ArrayList<Car>(carService.findAllServices(0, 10000));
for(int i=0;i<listcar.size();i++) {
System.out.println("The all car services in run method "+listcar.get(i).getName());
}
}
}
TestThreadCallController.java:
#Controller
public class TestThreadCallController {
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public #ResponseBody void FindyourCarService() throws IOException{
TestThread th=new TestThread(listcar);
new Thread(th).start();
ApplicationContext context = new ClassPathXmlApplicationContext("test-Thread.xml");
TestThread th1 = (TestThread) context.getBean("TestThread");
new Thread(th1).start();
}
}
test-Thread.xml
bean initialization code:
<bean id="TestThread" class="com.test.thread.domain.TestThread">
</bean>
Yeah, agree, bad idea doing this manually. Let Spring do it. Put a service for the DB behind A Spring Integration gateway & return a Future. boom. done. #Async works - but its more fun to play with SI.

How to write unit test which creates new thread

I have following method for test:
public class classToTest{
#Autowired
private Alternator alternator;
public void methodToTest(){
Thread t = new Thread(new Runnable() {
public void run() {
while(true) {
if(alternator.get()) {
System.out.print("Hello");
alternator.set(false);
}
}
}
};
t.start()
}
}
I need to check that was invoked method
alternator.set(false);
How can I do it?
Instead of starting a thread directly, can you pass in an "Executor" instance?
For example...
public class ClassToTest{
#Autowired
private Alternator alternator;
#Autowired #Qualifier("myExecutor")
private java.util.concurrent.Executor executor;
public void methodToTest() {
Runnable runnable = new Runnable() {
public void run() {
while(true) {
if(alternator.get()) {
System.out.print("Hello");
alternator.set(false);
}
}
};
executor.execute(runnable);
}
}
Now you can test this easier...
public class ClassToTestTest {
...
#Before
public void setup() {
alternator = mock(Alternator.class);
executor = mock(Executor.class);
obj = new ClassToTest();
ReflectionTestUtils.setField(obj, "alternator", alternator);
ReflectionTestUtils.setField(obj, "executor", executor);
}
#Test
public void shouldStartRunnable() {
obj.methodToTest();
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
verify(executor).execute(runnableCaptor.capture());
Runnable runnable = runnableCaptor.getValue();
// Now test your actual "runnable"...
when(alternator.get()).thenReturn(true);
runnable.run();
verify(alternator).set(false);
}
}
(Have not tried to compile this, so I apologise if there are any mistakes!!)
Though Bret's post of passing in an executor is very much recommended, you can use the timeout() mock verification setting to test for asynchronous conditions.
verify(alternator, timeout(500)).set(false);
Note that this will necessarily increase the flakiness of your test (i.e. the likelihood that the test fails when the code passes). With a sensible timeout value, that flakiness should be negligible, but if you're making this a part of your core test infrastructure you may consider refactoring to allow for synchronous execution in the test.

Notify the calling method about the exception occured in thread

I am writing an Spring-mvc application.
I am executing task using ThreadPoolTaskExecutor.
I have below sample code.
MyClass.java
public class MyClass {
public void startProcess() {
ThreadPoolTaskExecutor taskExecutor = //Initializing
for (int i = 1; i <= 5; i++) {
taskExecutor.execute(new MyRunnable());
// I can call taskExecutor.submit(task); also, if required
}
}
}
MyRunnable.java
public class MyRunnable implements Runnable {
#Override
public void onRun() {
try {
//Code which generates exception like below
throw new Exception("Runtime Exception");
} catch (Exception e1) {
// log or throw the exception
}
}
}
I want to notify startProcess() about the exception occurred in MyRunnable's run method.
Can any one please guide me for this.
I found below links but it is not solving my problem.
Handling exceptions from Java ExecutorService tasks
http://java.dzone.com/articles/spring-async-and-exception
Thanks.
Edit:
One more question. If I am using #Async for asynchronous call to my some other method and If I want to check for the exception occured in async method then what should I do? As async method also returns future object.
Answer for #Async question I got from here
Instead of Runnable, implement Callable. A Callable can throw an exception, and when you retrieve the result of the Callable using a Future, you will get the exception thrown as an ExecutionException:
public class MyCallable implements Callable<Void> {
public Void call() throws Exception {
try {
//Code which generates exception like below
throw new Exception("Runtime Exception");
} catch (Exception e1) {
// log or throw the exception
}
return null; // To satisfy the method signature
}
}
In MyClass:
List<Future<Void>> futures = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
Future<Void> future = taskExecutor.submit(new MyCallable());
futures.add(future);
}
// After all tasks have started, now wait for all of them to complete (they run in parallel)
// and check if there were any exceptions
for (Future<Void> future : futures) {
try {
future.get();
} catch (ExecutionException e) {
// Access the exception thrown by the different thread.
e.getCause().printStackTrace();
}
}
You can add constructor with some listener to your Thread.
Like:
ExceptionListener:
public class ExceptionListener{
public void doSomething(long threadId,Exception e){
//...e.g., notify startProcess()
}
}
MyRunnable:
public class MyRunnable implements Runnable {
private ExceptionListener listener;
private MyRunnable(ExceptionListener exception) {
this.listener = listener;
}
#Override
public void run() {
//...
listener.doSomething(Thread.currentThread().getId(),new Exception("Runtime Exception"));
//...
}
}
startProcess():
public void startProcess() {
ThreadPoolTaskExecutor taskExecutor = //Initializing
ExceptionListener listener= new ExceptionListener();
for (int i = 1; i <= 5; i++) {
taskExecutor.execute(new MyRunnable(listener();
// I can call taskExecutor.submit(task); also, if required
}
}
Or, you can use Thread.UncaughtExceptionHandler, like described here.
edited.
Clarification:
if exception occurs, I have to stop my further execution of other
processes. So I want to catch or get notified about the exception in
startProcess method. – Naman Gala 1 hour ago
Answer:
I suppose that your worker thread will have while cycle. So you can just pass volatile
boolean to each thread and set it up to true or
false in case of exception, cycle condition will be this boolean
variable. – Maksym 58 mins ago

Categories