Rxjava - Can I invoke `Subject.onNext` method from different threads? - java

I have a Spring web server and I want to create a chat room for every N (for example 10) clients that requests my controller.
Every request to server has its own thread, how to collect every N request and create for example a room for it? I think that Rxjava has a solution for this so how can I implement this and if I can't do this, what's the best solution?
Update 1:
With help of #pavan-kumar answer I created this:
#RestController
public class GameController {
private final PublishSubject<Integer> subject;
private AtomicInteger counter = new AtomicInteger(0);
#Autowired
public GameController(PublishSubject<Integer> subject) {
this.subject = subject;
}
#PostConstruct
public void init() {
subject.buffer(10).subscribe(
integers -> {
StringBuilder builder = new StringBuilder("[ ");
for (Integer integer : integers) {
builder = builder.append(integer).append(", ");
}
String s = builder.append("]").toString();
System.out.println(s);
});
}
#RequestMapping(value = "/game", method = RequestMethod.GET)
public void findNewGame() {
int i = counter.addAndGet(1);
subject.onNext(i);
}
}
So current question is "Can I invoke Subject.onNext method from different threads?"

Not directly. You have to provide serialization in some way or use the toSerialized() method and communicate with the returned Subject<T, R> instance.
PublishSubject<Integer> ps = PublishSubject.create();
Subject<Integer, Integer> subject = ps.toSerialized();
subject.subscribe(System.out::println);
subject.onNext(1);

Though the use case is not very clear for me, the below approach would probably help.
Every request to server has its own thread - Use a static Observable shared amongst all threads. May be you can call onNext every time a new user establishes a connection.
Once you have such Observable, you can subscribe to it via a buffer as depicted below.
Observable.range(1, 50).buffer(10).subscribe(n -> System.out.println(n.get(0)));
Observable.range(1, 50) is similar to your static Observable which emits events every time a connection is established. buffer takes care of merging all the items into a List of items and emits that one List when the said number of items(10) are emitted. You can subscribe on this and take appropriate actions as needed.

Related

What would be the best approach to use CompletableFuture while running a stream of asynchronous tasks?

I have a spring component EventSvcFacade which HAS-A list of three EventValidationSvc implementation class instances. Each of these classes implements the method boolean validate(T request), takes the same input but calls different APIs on the input, processes the result, and returns a boolean. This flow is thus designed for concurrent invocation. I have figured out two approaches to return a list of Boolean from the stream of tasks. Can anyone suggest, on what factors one approach is better than the other, or is there any other better approach?
#Component
public class EventSvcFacade {
#Autowired
private List<EventValidationSvc<EventRequest>> validationSvcs;
#Autowired
private ThreadPoolExecutor threadPoolExecutor;
public List<Boolean> firstApproach(){
final List<CompletableFuture<Boolean>> futures = validationSvcs.stream().map(service ->
CompletableFuture.supplyAsync(() -> service.validate(eventRequest), threadPoolExecutor))
.collect(Collectors.toList());
final List<Boolean> values = futures.stream().map(CompletableFuture ::
join).collect(Collectors.toList());
return values;
}
public List<Boolean> secondApproach() {
final List<Boolean> values = Collections.synchronizedList(new ArrayList<>());
final CountDownLatch countDownLatch = new CountDownLatch(validationSvcs.size());
validationSvcs.stream().forEach(service -> CompletableFuture.runAsync(() -> {
try{
values.add(service.validate(eventRequest));
}finally{
countDownLatch.countDown();
}
}, threadPoolExecutor)
);
countDownLatch.await();
return values;
}
}
The first approach is cleaner as it is pure: since it does not rely on side effects it is easier to reason about and less likely to break when code is modified later.
Also the first approach does not rely on ad-hoc synchronisation constructs such like the second approach does with the CountDownLatch instance. Should your preconditions change and there only be two services to call, the first approach will continue to work while the second one would never return.

Use ExecutorCompletionService to perform concurrent calls to different dependencies

I am trying to use the ExecutorCompletionService - https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorCompletionService.html, to try and perform concurrent calls to two different dependent packages.
The reason I am using ExecutorCompletionService is because I want to compare the results returned by both the dependencies and then emit a metric based on a specific requirement.
My code looks like this:
#Builder
#Slf4j
public class TestClass {
#NonNull private final ExecutorService threadPool = Executors.newFixedThreadPool(2);
#NonNull private final ExecutorCompletionService<ResultStructure1> dependency1Thread = new ExecutorCompletionService<>(threadPool);
#NonNull private final ExecutorCompletionService<ResultStructure2> dependency2Thread = new ExecutorCompletionService<>(threadPool);
public void myMethod() {
RequestObject1 firstDependencyRequest = RequestObject1.builder()
.attribute1("someValue")
.attribute2("secondValue");
RequestObject2 secondDepdencyRequest = RequestObject1.builder()
.attribute1("depdency2Value")
.attribute2("depdency2Secondvalue");
dependency1Thread.submit(() -> dependency1Client1.call(firstDependencyRequest));
dependency2Thread.submit(() -> dependencyClient2.call(secondDepdencyRequest));
final Future<ResultStructure1> future1 = dependency1Thread.take();
final Future<ResultStructure2> future2 = dependency2Thread.take();
try {
ResultStructure1 = future1.get();
ResultStructure2 = future2.get();
} catch (ExecutionException e) {
log.error("Exception calling dependency", e);
throw e;
}
}
}
Is this the correct way to be using ExecutorCompletionService for different dependencies? Is there a way to have a single executorService and have both the dependencies be called from that?
Is this the correct way to be using ExecutorCompletionService for
different dependencies?
Unfortunately, no. You'd typically use it to execute tasks returning similar type of results while you wait for their execution and their results to be available. Internally it uses a BlockingQueue where it adds the Futures as the tasks complete, which is then returned by its blocking take method.
So, if you do want to use an ExecutorCompletionService, you'd have to come up with a base/common type for ResultStructure1 and ResultStructure2 (i.e., ResultStructure), and declare a completion service like below -
private final ExecutorCompletionService<ResultStructure> completionService =
new ExecutorCompletionService<>(threadPool)
and then -
completionService.submit(() -> dependency1Client1.call(firstDependencyRequest));
completionService.submit(() -> dependencyClient2.call(secondDepdencyRequest));
You can then wait for their results to be available using the blocking take method -
Future<ResultStructure> result1 = completionService.take();
Future<ResultStructure> result2 = completionService.take();
Please note that at this point, we have no way of finding out which Future represents which concrete result type. So you have no way of comparing the results.
My recommendation would be to simply use ExecutorService directly.

CompletableFuture across microservices(JVM)

Step 1: I would like to have one CompletableFuture<String> asyncFuture starts in microservice A running a async task via say supplyAsync.
Step 2: Then manually complete the same future object by calling manually calling asyncFuture.complete(T value) from a DIFFERENT microservice B which would be triggered by some async event.
Apparently microservice A and microservice B have different JVMs.
In reality microservice A and microservice B are different instance of the same microservice running on different pods in kubernetes.
Between Step 1 and Step 2 , the future object will be stored in Redis which microservice B can retrieve safely.
After some quick googling, I think I am gonna try a couple of solution below:
1> HazelCast's Distributed Executor Service which I can pass in as a second parameter when calling
static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
Ref:
http://docs.hazelcast.org/docs/2.3/manual/html/ch09.html
2>Use shared executorService from apache ignite
Ref: https://apacheignite.readme.io/v1.2/docs/executor-service
Not sure if either would work ? Also I am wondering has anyone has dealt with something like this before ? If so I would appreciate if you could share your solution with me.
Regarding Apache Ignite, there are a lot of options how to cooperate nodes (microservices). One of them is Continuous Queries [1] which allow listening to data modifications occurring on caches.
For example, on service A you can create ContinuousQuery and wait for value is changed in the cache:
private String waitForValueChanged(IgniteCache<Integer, String> cache, Integer key) throws InterruptedException {
ContinuousQuery<Integer, String> qry = new ContinuousQuery<>();
qry.setInitialQuery(new ScanQuery<>((k, v) -> k == key));
final CountDownLatch waitForValueChanged = new CountDownLatch(1);
final AtomicReference<String> result = new AtomicReference<>();
CacheEntryUpdatedListener<Integer, String> listener = new CacheEntryUpdatedListener<Integer, String>() {
#Override public void onUpdated(Iterable<CacheEntryEvent<? extends Integer, ? extends String>> iterable) throws CacheEntryListenerException {
for (CacheEntryEvent<? extends Integer, ? extends String> entry: iterable) {
result.set(entry.getValue());
}
waitForValueChanged.countDown();
}
};
qry.setLocalListener(listener);
try (QueryCursor<Cache.Entry<Integer, String>> cur = cache.query(qry);) {
waitForValueChanged.await(60000, TimeUnit.MILLISECONDS);
}
return result.get();
}
On service B you just need to put the value into the cache to "complete the future":
private void completeFuture(IgniteCache<Integer, String> cache, Integer key, String value) {
cache.put(key, value);
}
Here is an example project which shows how Continuous Queries work [2].
[1] https://apacheignite.readme.io/docs#section-continuous-queries
[2] https://github.com/gromtech/ignite-continuous-query-example

Java callable threading: keep configuration

I am setting up a simulator (for testing) of a server (Radius) which sends queries to another server (LDAP) using threads.
The queries need to be executed on a x per second basis.
I am using a scheduled thread pool executor with callable for this purpose so that I can create callables and submit them to the thread pool for execution.
Each thread should open its own connection and use it to query.
The thing is that I want the connection to be re-used by the same thread every time it is used.
To clarify:
If I have lets say a thread pool of 20 I want 20 connections to be created and used. (so I can send lets say 10.000 queries which will be processed in turn by the 20 threads/connections).
Now the (LDAP) server information to connect to is sent to the constructor of the callable and the callable sets up the connection for execution. Thereafter I retrieve the result using the future system of callable.
The problem with this is each time I create a callable the connection is being opened (and later closed of course).
I am looking for the best practice to keep the connections alive and them being re-used for each thread.
I have thought of some ways to implement this but they dont seem very efficient:
Use a connection pool inside my threadpool to retrieve a free connection when needed (Creates deadlock and other thread safety issues)
Use a static (or so) array with connections and using the thread number to retrieve its connection (Not foul proof either, see link)
What is the most efficient way of implementing this? <- old question, see edit for new question.
EDIT:
I was thinking because I cannot safely get a thread number, but the threadId is always unique, I can just use a
map<String/threadId, connection>
And pass the whole map (reference) to the callable. This way I can use something like: (pseudo code)
Connection con = map.get(this.getThreadId());
If (con == null){
con = new Connection(...);
map.put(this.getThreadId(), con)
}
It would also be possible to make the map static and just access it statically. This way I don't have to pass the map to the Callable.
This would be at least safe and doesnt force me to restructure my code.
New question:
What would be closer aligned with best practices; The above solution or Zim-Zam's solution?
And if the above is best, would it be better to go for the static solution or not?
I would implement this using a BlockingQueue that is shared between Callables, with the ScheduledThreadPoolExecutor putting x queries into the BlockingQueue every second
public class Worker implements Runnable {
private final BlockingQueue<Query> inbox;
private final BlockingQueue<Result> outbox;
public Worker(BlockingQueue<Query> inbox, BlockingQueue<Result> outbox) {
// create LDAP connection
this.inbox = inbox;
this.outbox = outbox;
}
public void run() {
try {
while(true) {
// waits for a Query to be available
Query query = inbox.take();
// execute query
outbox.add(new Result(/* result */));
}
} catch(InterruptedException e) {
// log and restart? close LDAP connection and return?
}
}
}
public class Master {
private final int x; // number of queries per second
private final BlockingQueue<Query> outbox = new ArrayBlockingQueue<>(4 * x);
private final BlockingQueue<Result> inbox = new ArrayBlockingQueue<>(4 * x);
private final ScheduledThreadPoolExecutor executor;
private final List<Future<?>> workers = new ArrayList<>(20);
private final Future<?> receiver;
public Master() {
// initialize executor
for(int i = 0; i < 20; i++) {
Worker worker = new Worker(inbox, outbox);
workers.add(executor.submit(worker));
}
receiver = executor.submit(new Runnable() {
public void run() {
while(!Thread.interrupted()) {
try {
Result result = inbox.take();
// process result
} catch(InterruptedException e) {
return;
}
}
}
}
}
executor.scheduleWithFixedDelay(new Runnable() {
public void run() {
// add x queries to the queue
}
}, 0, 1, TimeUnit.SECONDS);
}
Use BlockingQueue#add to add new Queries to outbox, if this throws an exception then your queue is full and you'll need to reduce the rate of query creation and/or create more workers. To break out of a worker's infinite loop call cancel(true) on its Future, this will throw an InterruptedException inside of the Worker.

Consumer(s)-Producer issue in webserver streaming an array of data

Producer-Consumer blog post states that:
"2) Producer doesn't need to know about who is consumer or how many consumers are there. Same is true with Consumer."
My problem is that I have an array of data that I need to get from the Webserver to clients as soon as possible. The clients can appear mid-calculation. Multiple clients at different times can request the array of data. Once the calculation is complete it is cached and then it can simply be read.
Exmaple Use Case: While the calculation is occurring I want to serve each and every datum of the array as soon as possible. I can't use a BlockingQueue because say if a second client starts to request the array while the first one has already used .take() on the first half of the array. Then the second client missed half the data! I need a BlockingQueue where you don't have to take(), but you could instead just read(int index).
Solution? I have a good amount of writes on my array, so I wouldn't want to use CopyOnWriteArrayList? The Vector class should work but would be inefficient?
Is it preferable to use a ThreadSafeList like this and just add a waitForElement() function? I just don't want to reinvent the wheel and I prefer crowd tested solutions for multi-threaded problems...
As far as I understand you need to broadcast data to subscribers/clients.
Here are some ways that I know for approaching it.
Pure Java solution, every client has a BlockingQueue and every time you broadcast a message you put it every queue.
for(BlockingQueue client: clients){
client.put(msg);
}
RxJava provides a reactive approach. Clients will be subscribers and ever time you emit a message, subscribers will be notified and they can choose to cancel their subscription
Observable<String> observable = Observable.create(sub->{
String[] msgs = {"msg1","msg2","msg3"};
for (String msg : msgs) {
if(!sub.isUnsubscribed()){
sub.onNext(msg);
}
}
if (!sub.isUnsubscribed()) { // completes
sub.onCompleted();
}
});
Now multiple subscribers can choose to receive messages.
observable.subscribe(System.out::println);
observable.subscribe(System.out::println);
Observables are a bit functional, they can choose what they need.
observable.filter(msg-> msg.equals("msg2")).map(String::length)
.subscribe(msgLength->{
System.out.println(msgLength); // or do something useful
});
Akka provides broadcast routers
This is not exactly a trivial problem; but not too hard to solve either.
Assuming your producer is an imperative program; it generates data chunk by chunk, adding each chunk to the cache; the process terminates either successfully or with an error.
The cache should have this interface for the produce to push data in it
public class Cache
public void add(byte[] bytes)
public void finish(boolean error)
Each consumer obtains a new view from the cache; the view is a blocking data source
public class Cache
public View newView()
public class View
// return null for EOF
public byte[] read() throws Exception
Here's a straightforward implementation
public class Cache
{
final Object lock = new Object();
int state = INIT;
static final int INIT=0, DONE=1, ERROR=2;
ArrayList<byte[]> list = new ArrayList<>();
public void add(byte[] bytes)
{
synchronized (lock)
{
list.add(bytes);
lock.notifyAll();
}
}
public void finish(boolean error)
{
synchronized (lock)
{
state = error? ERROR : DONE;
lock.notifyAll();
}
}
public View newView()
{
return new View();
}
public class View
{
int index;
// return null for EOF
public byte[] read() throws Exception
{
synchronized (lock)
{
while(state==INIT && index==list.size())
lock.wait();
if(state==ERROR)
throw new Exception();
if(index<list.size())
return list.get(index++);
assert state==DONE && index==list.size();
return null;
}
}
}
}
It can be optimized a little; most importantly, after state=DONE, consumers should not need synchronized; a simple volatile read is enough, which can be achieved by a volatile state

Categories

Resources