Recently, I'm working on a project where I have 2 make 2 asynchronous calls at the same time. Since I'm working with Quarkus, I ended up trying to make use of Mutiny and the vert.x library. However, I can not get my code working with Unis. In the below code, I would imagine that both Unis would be called and the Uni that returns fastest would be returned. However, it seems that when combining Unis it simply returns the first one in the list, even though the first uni should take a longer time.
The below code prints out one one when it should print out two two since the uniFast should finish first. How do I combine Unis and have the faster one return first?
#Test
public void testUniJion(){
var uniSLow = Uni.createFrom().item(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "one";
});
var uniFast = Uni.createFrom().item(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "two";
});
var resp = Uni.join().first(uniSLow,uniFast).withItem().await().indefinitely();
System.out.println(resp);
var resp2 = Uni.combine().any().of(uniSLow,uniFast).await().indefinitely();
System.out.println(resp2);
}
Note: This is not the actual code I am trying to implement. In my code, I am trying to fetch from 2 different databases. However, one database often has a lot more latency than the other. However, Uni seems to always wait for the slower database. I'm simply trying to understand Mutiny and Uni's better so I made this code example.
The problem is that you are not telling Mutiny on which thread should run each uni. If I add a System.out to your example:
// Slow and Fast for the different Uni
System.out.println( "Slow - " + Thread.currentThread().getId() + ":" + Thread.currentThread().getName() );
I get the following output:
Slow - 1:Test worker
one
Slow - 1:Test worker
Fast - 1:Test worker
one
The output shows that everything runs on the same thread and therefore when we block the first one, the second one is blocked too.
That's why the output is one one.
One way to run the uni in parallel is to use a different executor at subscription:
ExecutorService executorService = Executors.newFixedThreadPool( 5 );
uniSlow = uniSlow.runSubscriptionOn( executorService );
uniFast = uniFast.runSubscriptionOn( executorService );
Now, when I run the test, I have the expected output:
Slow - 16:pool-3-thread-1
Fast - 17:pool-3-thread-2
two
Slow - 18:pool-3-thread-3
Fast - 19:pool-3-thread-4
two
Note that this time Slow and Fast are running on different threads.
The Mutiny guide has a section about the difference between emitOn vs. runSubscriptionOn and some examples on how to change the emission thread.
Related
I'm .NET Developer but i have to make some code for Android in Java. I need to run 4 calculation operation and i want to make it in separate threads. I can simply create 4 thread and just run it but when device will have less than 4 cores ( e.g 1) it will be same or even less effective like just run in one thread. In C# i can create list of Action and then just run it in Parrarel like this :
C# CODE :
var actions = new List<Action>
{
() => { // some action1},
() => { // some action2},
() => { // some action3},
() => { // some action4},
}
Parallel.ForEach(actions, new ParallelOptions { MaxDegreeOfParallelism = GetCoreCount() }, x => x());
And this will run and this will guarantee that each Action will be process on separate core ( More-Less)
Can I do some thing like this in Java on Android ?
I have no idea how to start this.
Only one thing that come to my head is some like this but this is ugly and ineffective.
int cores = Runtime.getRuntime().availableProcessors();
if(cores = 1)
{
// Create 1 Thread with action1,action2,action3,action4
}
if(cores = 2)
{
// Create 1 Thread with action1,action2
// And Create 2nd Thread with action3,action4
}
if(cores = 3)
{
// Create 1 Thread with action1,
// And Create 2nd Thread with action2
// And Create 3rd Thread with action3
// Thread that first end his action will pick up Action4
}
if(cores >= 4)
{
// Create 1 Thread with action1,
// And Create 2nd Thread with action2
// And Create 3nd Thread with action3
// And Create 4th Thread with action4
}
See even not codded this look very unclear and dirty ( and what when i add 5th action ? or will have 8 action and 8 cores ? )
Can i do something similar to C# ? With List of Action and Parallel execution limited by numbers of core ?
Thanks for advises :)
Try using a threadPoolExecutor https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html
Java handles the efficiency issues your worried about, and fyi a computer with one core/cpu will have multiple threads running, there will only be one running at any given time. But any modern computer has a lot of threads running simultaneously, it doesn't depend on how many cores/cpus are present/available.
I have one unit test in which I am writing and reading from cassandra multiple times.
future = function(Cassandra update with value x) - async //write and read updated value
value = future.get(); //reading
print value;
assert value == x;
//doing the above operation multiple times with different values of x;
Running the same code multiple times is showing different results i.e printing different result for 'value' attribute.
I am using cassandra on local host with
replication = {
'class': 'SimpleStrategy',
'replication_factor': '1'
};
It's worth noting that I am writing and reading at a same row in the table (in all read and write, primary key is same).
And though I am modifying the same object multiple times, but they are supposed to run sequentially as I am running blocking function future.get() after every update statement.
I am using Cassandra 2.0.14 with datastax driver and jdk 1.8.
Any ideas why I must be facing such behaviour?
Figured out the reason.
In my code (not the test code), I wasn't actually writing and reading sequentially. Read wasn't waiting for the write to be completed.
What I was doing:
`CompletionStage<Void> Function() {
someOperation
.thenAccept(variable -> AsyncWriteInDb(variable));
}
// AsyncWriteInDb returns CompletionStage<Void> when write is completed.
// I was reading just after execution of this function.
`
What I should be doing:
` CompletionStage<Void> Function() {
someOperation
.thenCompose(variable -> AsyncWriteInDb(variable));
}
//AsyncWriteInDb returns CompletionStage<Void> when write is completed.
`
It's easier to understand if I write earlier (wrong) code part as below:
`CompletionStage<Void> Function() {
someOperation
.thenAccept(variable -> {
AsyncWriteInDb(variable);
return;
});
}
// thenAccept's lamda was returning after initiating an asyncDbWrite.
// Reading just after this doesnt ensure sequential reading after writing.
`
I've a web application which needs to be extremely fast. But for processing it requires access for multiple data sources. Therefore I decided that it might be useful to make a parallel calls for optimization.
Basically I want to make many different db calls in parallel. Could you please recommend me simple and reliable way and technologies for achieving my goal, it would be useful if you could provide few frameworks and design patterns.
Right now I am using Spring.
You can use the new Java 8 CompletableFuture. It allows to use asynchronously existing synchronous method.
Say you have a list of requests in the form List<DBRequest> listRequest that you want to run in parallel. You can make a stream and launching all requests asynchronously in the following way.
List<CompletableFuture<DBResult>> listFutureResult =
listRequest.stream()
.map(req -> CompletableFuture.supplyAsync(
() -> dbLaunchRequest(req), executor))
.collect(Collectors.toList());
List<DBResult> listResult =
listFutureResult.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
To be effective you have to write your own custom Executor
private final Executor executor =
Executors.newFixedThreadPool(Math.min(listRequest.size(), 100),
new ThreadFactory(){
public Thread newThread(Runnable r){
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
Like this you can have enough threads but not too much. Marking threads to deamons allows you to finish the program even if one thread is blocked.
You can find clear explanations about these techniques in the chapter 11 of the book Java 8 in action
== UPDATE for Java 7 ==
If you are stick with Java 7, you can use the following solution:
class DBResult{}
class DBRequest implements Callable<DBResult>{
#Override
public DBResult call(){return new DBResult();}
}
class AsyncTest{
public void test(){
try {
for(Future<DBResult> futureResult : ((ExecutorService)executor).invokeAll(listRequest)){
futureResult.get();
}
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(SoTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
All requests are run asynchronously and you then wait for their completion, in the order of the list.
Finally, to answer the subsidiary question in the comment, you don't have to create a thread pool for each request.
I am fairly new to Java and extremely new to concurrency. However, I have worked with C# for a while. It doesn't really matter, but for the sake of example, I am trying to pull data off a table on server. I want method to wait until data is completely pulled. In C#, we have async-await pattern which can be used like this:
private async Task<List<ToDoItem>> PullItems ()
{
var newRemoteItems = await (from p in remoteTable select p).ToListAsync();
return newRemoteItems;
}
I am trying to have similar effect in Java. Here is the exact code I'm trying to port (Look inside SynchronizeAsync method.)! However, Java Azure SDK works with callbacks. So, I have a few options:
Use wait and notify pattern. Following code doesn't work since I don't understand what I'm doing.
final List<TEntity> newRemoteItems = new ArrayList<TEntity>();
synchronized( this ) {
remoteTable.where().field("lastSynchronized").gt(currentTimeStamp)
.execute(new TableQueryCallback<TEntity>() {
public void onCompleted(List<TEntity> result,
int count,
Exception exception,
ServiceFilterResponse response) {
if (exception == null) {
newRemoteItems.clear();
for (TEntity item: result) {
newRemoteItems.add(item);
}
}
}
});
}
this.wait();
//DO SOME OTHER STUFF
My other option is to move DO SOME OTHER STUFF right inside the callback's if(exception == null) block. However, this would result in my whole method logic chopped off into the pieces, disturbing the continuous flow. I don't really like this approach.
Now, here are questions:
What is recommended way of doing this? I am completing the tutorial on Java concurrency at Oracle. Still, clueless. Almost everywhere I read, it is recommended to use higher level stuff rather than wait and notify.
What is wrong with my wait and notify?
My implementation blocks the main thread and it's considered a bad practice. But what else can I do? I must wait for the server to respond! Also, doesn't C# await block the main thread? How is that not a bad thing?
Either put DO SOME OTHER STUFF into callback, or declare a semaphore, and call semaphore.release in the callback and call semaphore.aquire where you want to wait. Remove synchronized(this) and this.wait.
I have been given the task of creating a sql database and creating a GUI in Java to access it with. I pretty much have it but I have a question about threads. Before today I did not use any threads in my program and as a result just to pull 150 records from the database i had to wait around 5 - 10 seconds. This was very inconvenient and I was not sure if i could fix the issue. Today I looked on the internet about using threads in programs similar to mine and i decided to just use one thread in this method:
public Vector VectorizeView(final String viewName) {
final Vector table = new Vector();
int cCount = 0;
try {
cCount = getColumnCount(viewName);
} catch (SQLException e1) {
e1.printStackTrace();
}
final int viewNameCount = cCount;
Thread runner = new Thread(){
public void run(){
try {
Connection connection = DriverManager.getConnection(getUrl(),
getUser(), getPassword());
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery("Select * FROM "
+ viewName);
while (result.next()) {
Vector row = new Vector();
for (int i = 1; i <= viewNameCount; i++) {
String resultString = result.getString(i);
if (result.wasNull()) {
resultString = "NULL";
} else {
resultString = result.getString(i);
}
row.addElement(resultString);
}
table.addElement(row);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
};
runner.start();
return table;
}
The only thing i really changed was adding the thread 'runner' and the performance increased exponentially. Pulling 500 records occurs almost instantly this way.
The method looked like this before:
public Vector VectorizeTable(String tableName) {
Vector<Vector> table = new Vector<Vector>();
try {
Connection connection = DriverManager.getConnection(getUrl(),
getUser(), getPassword());
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery("Select * FROM "
+ tableName);
while (result.next()) {
Vector row = new Vector();
for (int i = 1; i <= this.getColumnCount(tableName); i++) {
String resultString = result.getString(i);
if (result.wasNull()) {
resultString = "NULL";
} else {
resultString = result.getString(i);
}
row.addElement(resultString);
}
table.addElement(row);
}
} catch (SQLException e) {
e.printStackTrace();
}
return table;
}
My question is why is the method with the thread so much faster than the one without? I don't use multiple threads anywhere in my program. I have looked online but nothing seems to answer my question.
Any information anyone could give would be greatly appreciated. I'm a noob on threads XO
If you need any other additional information to help understand what is going on let me know!
Answer:
Look at Aaron's answer this wasn't an issue with threads at all. I feel very noobish right now :(. THANKS #Aaron!
I think that what you are doing is appearing to make the database load faster because the VectorizeView method is returning before the data has been loaded. The load is then proceeding in the background, and completing in (probably) the same time as before.
You could test this theory by adding a thread.join() call after the thread.start() call.
If this is what is going on, you probably need to do something to stop other parts of your application from accessing the table object before loading has completed. Otherwise your application is liable to behave incorrectly if the user does something too soon after launch.
FWIW, loading 100 or 500 records from a database should be quick, unless the query itself is expensive for the database. That shouldn't be the case for a simple select from a table ... unless you are actually selecting from a view rather than the table, and the view is poorly designed. Either way, you probably would be better off focussing on why such a simple query is taking so long, rather than trying to run it in a separate thread.
In your follow-up you say that the version with the join after the start is just as fast as the version without it.
My first reaction is to say: "Leave the join there. You've fixed the problem."
But this doesn't explain what is actually going on. And I'm now completely baffled. The best I can think of is that something your application is doing before this on the current thread is the cause of this.
Maybe you should investigate what the application is doing in the period in which this is occurring. See if you can figure out where all the time is being spent.
Take a thread dump and look at the threads.
Run it under the debugger to see where the "pause" is occurring.
Profile it.
Set the application logging to a high level and see if there are any clues.
Check the database logs.
Etcetera
It looks like you kick off (i.e. start) a background thread to perform the query, but you don't join to wait for the computation to complete. When you return table, it won't be filled in with the results of the query yet -- the other thread will fill it in over time, after your method returns. The method returns almost instantly, because it's doing no real work.
If you want to ensure that the data is loaded before the method returns, you'll need to call runner.join(). If you do so, you'll see that loading the data is taking just as long as it did before. The only difference with the new code is that the work is performed in a separate thread of execution, allowing the rest of your code to get on with other work that it needs to perform. Note that failing to call join could lead to errors if code in your main thread tries to use the data in the Vector before it's actually filled in by the background thread.
Update: I just noticed that you're also precomputing getColumnCount in the multi-threaded version, while in the single-threaded version you're computing it for each iteration of the inner loop. Depending on the complexity of that method, that might explain part of the speedup (if there is any).
Are you sure that it is faster? Since you start separate thread, you will return table immediately. But are you sure that you measure time after it's fully populated with data?
Update
To measure time correctly, save runner object somewhere and call runner.join(). You can even to it in the same method for testing.
Ok, I think that if you examine table at the end of this method you will find it's empty. That's because start starts running the thread in the background, and you immediately return table without the background thread having a chance to populate it. So it appears to be going faster but actually isn't.