Why does reactive stream subscriber is executed in current thread? - java

subscribe documentation states:
Keep in mind that since the sequence can be asynchronous, this will
immediately return control to the calling thread. This can give the
impression the consumer is not invoked when executing in a main thread
or a unit test for instance.
So why do I see every element printed out? It means that lambda is executed in the main thread
import reactor.core.publisher.Flux;
import java.util.concurrent.TimeUnit;
public class ReactorMain {
public static void main(String[] args) {
Flux.just(1,2,3,4,5,6,7,8,9,10)
.limitRequest(5)
.skip(3)
.subscribe(value -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Value: " + value);
})
;
}
}

This is because the generation of values does not contain any asynchronous element. So when you subscribe to the Flux, it will use the current thread to do as many thing it can do, until an asynchronous element makes it wait and use the thread for something else.
If to produce your elements you are for example calling a web service in an asynchronous way, you will receive values in an asynchronous way.
You can test it by making the sequence delayed:
public static void main(String[] args) {
Flux.just(1,2,3,4,5,6,7,8,9,10)
.limitRequest(5)
.skip(3)
.delayElements(Duration.ofSeconds(2))
.subscribe(value -> {
System.out.println("Value: " + value);
})
;
}

Related

Spring controller how to serve only 1 request each time, and discard other requests received for the same method until first request has finished

So as the title describes I want to achieve the following
#Controller
public class ImportController {
#RequestMapping(value = "/{File}", method = RequestMethod.GET)
#LogAware
public String import(#PathVariable(value = "File") String excel, Model model) {
try {
synchronized (this) {
//code...
}
}
}
}
I want the code to be executed only for 1 request that comes at a time. The execution of the code inside the synchronized block can last about 1 hour. In the mean time I would like each other request that arrives to that method to be cancelled. Is there any way to achieve that?
Just to clarify:
As it is right now the first request will be served and when it finishes the next request that was waiting for the lock will be served and then the next that was waiting.
What I want is to not allow other requests which are already waiting to be served after the first request finishes. If the requests came during the execution of the first request I want to return bad request or something else to the user and to cancel their request.
Approach 1:
Use a single permit Semaphore
Here's a sample code:
import java.util.concurrent.Semaphore;
public class Test {
Semaphore s = new Semaphore(1); // Single permit.
public void nonBlockingMethod() throws InterruptedException {
// A thread tries to acquire a permit, returns immediately if cannot
if (s.tryAcquire()) {
// No. of permits = 0
try {
System.out.println(Thread.currentThread().getName() + " begins execution..");
// long running task
Thread.sleep(4000);
System.out.println(Thread.currentThread().getName() + " exiting..");
} finally {
s.release(); // Release permit. No. of permits = 1
}
} else {
System.out.println(Thread.currentThread().getName() + " cannot run as another thread is already running..");
}
}
}
Approach 2:
Use a ReentrantLock
Sample Code:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
Lock s = new ReentrantLock();
public void nonBlockingMethod() throws InterruptedException {
if (s.tryLock()) {
try {
System.out.println(Thread.currentThread().getName() + " begins execution..");
// long running task
Thread.sleep(4000);
System.out.println(Thread.currentThread().getName() + " exiting..");
} finally {
s.unlock();
}
} else {
System.out.println(Thread.currentThread().getName() + " cannot run as another thread is already running..");
}
}
}
Driver:
public static void main(String[] args) throws InterruptedException {
Test t = new Test();
Runnable r = () -> {
try {
t.nonBlockingMethod();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
for (int i = 0; i < 3; i++) {
new Thread(r, "Loop-1-Thread-" + i).start();
}
Thread.sleep(3999);
// one of the threads in this iteration may get to run the task
for (int i = 3; i < 8; i++) {
new Thread(r, "Loop-2-Thread-" + i).start();
}
}
(one of the) Output (s):
Loop-1-Thread-2 cannot run as another thread is already running..
Loop-1-Thread-1 cannot run as another thread is already running..
Loop-1-Thread-0 begins execution..
Loop-2-Thread-3 cannot run as another thread is already running..
Loop-2-Thread-4 cannot run as another thread is already running..
Loop-2-Thread-5 cannot run as another thread is already running..
Loop-1-Thread-0 exiting..
Loop-2-Thread-6 begins execution..
Loop-2-Thread-7 cannot run as another thread is already running..
Loop-2-Thread-6 exiting..
This is an approach that you can consider. This uses a global state in an AtomicBoolean which is safe (?) to use in your use case, hopefully!
See this SO When do I need to use AtomicBoolean in Java?
static AtomicBoolean atomicBoolean = new AtomicBoolean(false);
//controller definition
if(atomicBoolean.compareAndSet(false, true)) {
// your logic
atomicBoolean.compareAndSet(true, false);
}
// rest of the controller logic
But, do consider an option of queueing the requests and processing them as a background task or so. Keeping the socket and HTTP open for longer times is not recommended in most cases.

Why Parallel execution not happening for multiple RXJava Observables?

I am new to RxJava and was trying to execute an example of parallel execution for multiple Observables from link :
RxJava Fetching Observables In Parallel
Though the example provided in the above link is executing observables in parallel, but when I added a Thread.sleep(TIME_IN_MILLISECONDS) in the forEach method then the system started executing one Observable at a time. Please help me to understand that why Thread.sleep is stopping the parallel execution of Observables.
Below is the modified example which is causing synchronous execution of multiple observables :
import rx.Observable;
import rx.Subscriber;
import rx.schedulers.Schedulers;
public class ParallelExecution {
public static void main(String[] args) {
System.out.println("------------ mergingAsync");
mergingAsync();
}
private static void mergingAsync() {
Observable.merge(getDataAsync(1), getDataAsync(2)).toBlocking()
.forEach(x -> { try{Thread.sleep(4000);}catch(Exception ex){};
System.out.println(x + " " + Thread.currentThread().getId());});
}
// artificial representations of IO work
static Observable<Integer> getDataAsync(int i) {
return getDataSync(i).subscribeOn(Schedulers.io());
}
static Observable<Integer> getDataSync(int i) {
return Observable.create((Subscriber<? super Integer> s) -> {
// simulate latency
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
s.onNext(i);
s.onCompleted();
});
}
}
In the above example we are using the subscribeOn method of observable and providing a ThreadPool(Schedules.io) for execution, so subscription for each Observable will happen on separate thread.
There is a possibility that Thread.sleep is locking any shared object between threads but I am still not clear on it. Please help.
Actually, with your example parallel execution is do happening, you are just looking at it incorrectly, there is a difference between where the work is executed and where the notification are emitted.
if you will put the log with the thread id at Observable.create, you will notice each Observable is executed at different thread simultaneously. but the notification is happens serially. this behavior is as expected as part of Observable contract is that observables must issue notifications to observers serially (not in parallel).

How to make some asynch calls in a loop

In a loop i need to make some checks, performed actually in some another verticle. In each iteration of my loop i need to check the response code, returned from those verticle and make some decision accordingly. In some other words i need to stop the execution of my loop and somehow wait till asynch. call returns. But such execution stop violates the vert.x philosophy, which states that main thread execution should be never stopped. How can i do it in the scope of Vert.x? So far i don't know how to do this. Any suggestions/code samples/urls to smth. like a solution would b highly appreciated.
Thanks!
When working with Vert.x you need to think less in terms of loops, and more in terms of callbacks.
You should use eventBus to communicate between vertices.
Let's say that what you want is something similar to this pseudocode:
for (int i = 0; i < 4; i++) {
int result = getVerticleResult();
System.out.println(result);
}
So, just a very basic example
class LooperVerticle extends AbstractVerticle {
private int i = 4;
#Override
public void start() throws Exception {
doWork();
}
private void doWork() {
vertx.eventBus().send("channel", "", (o) -> {
if (o.succeeded()) {
System.out.println(o.result().body());
i--;
if (i > 0) {
doWork();
}
}
});
}
}
class WorkerVerticle extends AbstractVerticle {
#Override
public void start() throws Exception {
vertx.eventBus().consumer("channel", (o) -> {
// Generate some random number
int num = ThreadLocalRandom.current().nextInt(0, 9);
// Simulate slowness
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
o.reply(num);
});
}
}
To test:
public class EventBusExample {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new LooperVerticle());
vertx.deployVerticle(new WorkerVerticle());
}
}
I think you need to use FutureTask and store them in a Collection and use FutureTask.get() to retrieve the result when needed which is a blocking call.
It sounds like a use case for reactive steam processing.
In general such problem could be solved using 2 parties:
a producer that executes tasks and returns asynchronous results
a handler that subscribes to results and performs another tasks
There is a way to configure producer to perform tasks only when there is a subscriber. And on other side subscriber can decide to unsubscribe from producer on some condition.
I'm not familiar with vertx capabilities for reactive streams. But I would start from RxJava integration
http://vertx.io/docs/vertx-rx/java/

AOP Using Around to avoid executing a method

I am using Spring AOP in my code to intercept the execution of a certain method. A simplified example of what I'm trying to do is below:
public void someMethod() {
//does something
}
#Around("execution( someMethod())")
public void anotherMethod(final ProceedingJoinPoint joinPoint) {
//i want to add this to a queue to get executed later on
addToWaitList(new Callable() {
#Override
public call() throws Exception {
joinPoint.proceed();
}
});
return;
}
Essentially, I want to hold off the execution of someMethod() until it is at the head of the list. However, the main thread blocks, even though I return at the end of anotherMethod(), so I am unable to add a new Callable to the list until the first one is done executing.
The documentation says you can shortcut the advised method execution by returning its own return value or throwing an exception. I don't want to throw an exception and am not really sure what "returning its own return value" means in this case. I want to be able to add the Callables to the list with the main thread and then have some other threadpool executing them.
What you wish to implement is the worker object pattern. I have created a small example for you showing how you can intercept method calls with by a certain naming pattern, but with variable return types and parameters. See my own answer there for a more complex example.
Driver application:
public class Application {
public static void main(String[] args) {
System.out.println("Starting up application");
Application app = new Application();
app.doThis(11);
app.doThat();
app.doThis(22);
System.out.println("Shutting down application");
}
public void doThis(int number) {
System.out.println("Doing this with number " + number);
}
public String doThat() {
String value = "lorem ipsum";
System.out.println("Doing that with text value '" + value + "'");
return value;
}
}
Aspect implementing worker object pattern:
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Callable;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class QueuedExecutionAspect {
Queue<Callable<Object>> waitList = new LinkedList<Callable<Object>>();
private void addToWaitList(Callable<Object> callable) {
waitList.add(callable);
}
#Around("execution(public * Application.do*(..))")
public Object anotherMethod(final ProceedingJoinPoint joinPoint) {
System.out.println(joinPoint + " -> adding to execution queue");
addToWaitList(new Callable<Object>() {
#Override
public Object call() throws Exception {
try {
joinPoint.proceed();
} catch (Throwable e) {
throw new Exception(e);
}
return null;
}
});
return null;
}
#After("execution(public * Application.main(..))")
public void doDelayedExecution(JoinPoint joinPoint) throws Exception {
System.out.println("\nDelayed executions:");
while (!waitList.isEmpty()) {
waitList.poll().call();
}
}
}
Output:
Starting up application
execution(void Application.doThis(int)) -> adding to execution queue
execution(String Application.doThat()) -> adding to execution queue
execution(void Application.doThis(int)) -> adding to execution queue
Shutting down application
Delayed executions:
Doing this with number 11
Doing that with text value 'lorem ipsum'
Doing this with number 22
As you can see from the output, the #Around advice terminates normally after having added the Callable worker object to the queue, application execution continues without proceed() having been called. For illustration I added another advice which runs all elements from the FIFO queue (other queue types can be used according to your needs) before the application exits.

Java Threads design

I have thread application which process heavy task, i would like to trigger forcibly stop thread upon external flag information. I have tried following design,
public class HeavyTaskThread implements Runnable
{
private boolean forceStop;
public void run()
{
..
..
..
..
}
}
Another fact is i do not have control of logic flow implemented into method run(); which simply call some third-party program. I was trying with light inner thread class and calling method interrupt() on parent thread, but this does not work.
Please suggest any pattern....
The recommended way to handle the activity of third-party code that you have no control over is to launch it as a different process instead. Then simply kill the process when you need to forcibly stop the code. It's much more clean and safe than killing a thread, since it does not affect the parent process and the OS will take care of the cleanup duty.
If the third party program doesn't respond to an interrupt or setting a condition, an icky option is to try to kill it by nulling a key variable, closing a socket or file, etc. And hoping that it terminates gracefully. Like I said, icky but sometimes you gotta do what you gotta do...
If whatever third-party program you call in run() never returns, you're out of luck. If it returns periodically, you can make it loop, checking against a volatile forceStop boolean and exiting the loop when it's true:
private volatile boolean forceStop;
public void run()
{
while(!forceStop) {
..
..
}
}
While I'd vote for Tudor's answer, in the extreme and if you're desperate:
Option A - Reconstruct problem code.
Use your favorite java decompiler & re-create problem class.
Add check for Thread.currentThread().isInterrupted() into run.
Compile, place your modified class before original library in the classpath.
If the original jar was signed you may have to eliminate related signature artifacts.
Option B - Aspect J
Examine source for the run method, use your favorite java decompiler if necessary.
Identify a some reasonable point in the inner loop for stepping in and stopping.
Examine exception handling in code. Any loop-holes?
Inject code: throw exceptions, catch exceptions, etc. as needed to back out and return from run.
Here is final analysis...for killing thread.
Using Thread to control the execution of Program B. But then stopping a process means via a thread is not allowed as the related methods are deprecated (stop/suspend etc.,)
Using ThreadGroup ( to have only one thread as its member) and calling 'destroy' on the group. But it again falls on the same track as every thread should be stopped before the destroy operation is attempeted.
Process/ProcessBuilder via Runtime seems to be the better way to obtain a process reference and call destroy(), waitFor() etc. as user #Tudor mentioned.
Here is exact outlined code i have tried and it fails to kill, commented line while(isValid()) represents my another java program invoke.
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
class TaskWorker implements Callable {
private final int number;
public TaskWorker(int number) {
this.number = number;
}
public Boolean call() throws InterruptedException {
while (!Thread.currentThread().isInterrupted()) {
myBusyFunction();
}
return true;
}
private boolean isValid() {
return true;
}
private void myBusyFunction() {
//while (isValid()) {
System.out.println(number + ">....Working.....");
//}
}
}
public class Test {
public static void main(final String[] args) {
CompletionService cs = new ExecutorCompletionService(Executors.newFixedThreadPool(1));
Collection tasks = new ArrayList(10);
tasks.add(new TaskWorker(1));
List> futures = new ArrayList>(tasks.size());
try {
for (Callable task : tasks) {
futures.add(cs.submit(task));
}
//----
for (int t = 0; t result = cs.poll(10, TimeUnit.SECONDS);
if (result == null) {
System.out.println(new Date() + ":Worker Timedout:");
//So lets cancel the first futures we find that havent completed
for (Future future : futures) {
System.out.println("Checking future");
if (future.isDone()) {
continue;
} else {
future.cancel(true);
System.out.println("Cancelled");
break;
}
}
continue;
} else {
try {
if (result.isDone() && !result.isCancelled() && result.get()) {
System.out.println(new Date() + ":Worker Completed:");
} else if (result.isDone() && !result.isCancelled() && !result.get()) {
System.out.println(new Date() + ":Worker Failed");
}
} catch (ExecutionException ee) {
ee.printStackTrace(System.out);
}
}
}
} catch (InterruptedException ie) {
} finally {
//Cancel by interrupting any existing tasks currently running in Executor Service
for (Future f : futures) {
f.cancel(true);
}
}
System.out.println(new Date() + ":Done");
}
}

Categories

Resources