I am using volley singleton and add all volley request to it.
sample code of adding volley request to queue
MyApplication.getInstance().addToReqQueue(jsObjRequest, "jreq1");
I have an onclick function.
buttonId.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for(int i=0;i<4;i++){
//....... here i call for asycn volley requests which get added to the queue of volleysingleton
}
// ******how to ensure all my volley requests are completed before i move to next step here.*****
//calling for new intent
Intent m = new Intent(PlaceActivity.this, Myplanshow.class);
m.putExtra("table_name", myplansLists.get(myplansLists.size() - 1).table_name);
m.putExtra("table_name_without_plan_number", myplansLists.get(myplansLists.size() - 1).place_url_name);
m.putExtra("changed", "no");
m.putExtra("plannumber", myplansLists.size());
//moving to new intent;
v.getContext().startActivity(m);
}
});
Inside onclick i have a for loop which will execute multiple volley requests.
After the for loop it will start a new activity through intent.
But for my new activity to show, i need the data of all the volley requests in the for loop to be completed before, it leaves this activity and goes to new activity.
My approach basically is to set up 2 int variables: successCount and errorCount that I use to monitor the volley requests. In the onResponse of each request, I increment the successCount variable, then in the onErrorResponse, I increment the errorCount. At the end, I check if the sum of both variables equals the number of requests made, if its not, the thread waits in a loop.
check this:
buttonId.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Runnable(){
#Override
public void run() {
int successCount=0;
int errorCount=0;
for(int i=0;i<4;i++){
//....... here i call for asycn volley requests which get added to the queue of volleysingleton
//in the onResponse of each of the volley requests, increment successCount by 1;
// i.e successCount++;
//also in onErrorResponse of each of the volley requests, increment
// errorCount by 1
}
// ******how to ensure all my volley requests are completed before i move to next step here.*****
// wait here till all requests are finished
while (successCount+errorCount<4)
{
Log.d("Volley"," waiting");
}
//calling for new intent
Intent m = new Intent(PlaceActivity.this, Myplanshow.class);
m.putExtra("table_name", myplansLists.get(myplansLists.size() - 1).table_name);
m.putExtra("table_name_without_plan_number", myplansLists.get(myplansLists.size() - 1).place_url_name);
m.putExtra("changed", "no");
m.putExtra("plannumber", myplansLists.size());
//moving to new intent;
v.getContext().startActivity(m);
}
}.run();
}
});
Related
I needed to call two downstream systems parallelly with non-blocking io from Spring flux-based my rest service API. But the first downstream system capacity is 10 requests at a time and the second downstream system is 100.
The first downstream system out is input to the second downstream system so I can make a more parallel request to the second system to expedite the process.
The second downstream system response is very large so unable to hold in memory to concrete all the response So immediate want to return the response to the client.
Ex workflow:
Sample Code:
#GetMapping(path = "/stream", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
public Flux<String> getstream() {
ExecutorService executor = Executors.newFixedThreadPool(10);
List<CompletableFuture> list = new ArrayList<>();
AtomicInteger ai = new AtomicInteger(1);
RestTemplate restTemplate = new RestTemplate();
for (int i = 0; i < 100; i++) {
CompletableFuture<Object> cff = CompletableFuture.supplyAsync(
() -> ai.getAndAdd(1) + " first downstream web service " +
restTemplate.getForObject("http://dummy.restapiexample.com/api/v1/employee/" + ai.get(), String.class)
).thenApplyAsync(v -> {
Random r = new Random();
Integer in = r.nextInt(1000);
return v + " second downstream web service " + in + " " + restTemplate.getForObject("http://dummy.restapiexample.com/api/v1/employee/" + ai.get() + 1, String.class) + " \n";
}, executor);
list.add(cff);
}
return Flux.fromStream(list.stream().map(m -> {
try {
return m.get().toString();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return "";
})
);
}
This code only working for the first five threads after I am getting a response all threads completed the process. But I needed to get a response immediately to the client once I am getting the response from the second downstream system.
Note: The above code is not implemented with a second level thread pool.
Thank you in advance.
If you're building non-blocking system using Spring-Webflux it's better to utilise capabilities of WebClient in your example. I've created a simple test application where the below code snippet worked for me:
private final WebClient w = WebClient.create("http://localhost:8080/call"); // web client for external system
#GetMapping(path = "/stream", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
public Flux<MyClass> getstream() {
return Flux
.range(0, 100) // prepare initial 100 requests
.window(10) // combine elements in batch of 10 (probably buffer will fit better, have a look)
// .delayElements(Duration.ofSeconds(5)) for testing purpose you can use this function as well
.doOnNext(flow -> log.info("Batch of 10 is ready")) // double check tells that batch is ready
.flatMap(flow -> flow
// perform an external async call for each element in batch of 10
// they will be executed sequentially but there will not be any performance issues because
// calls are async. If you wish you can add .parallel() to the flow to make it parallel
.flatMap(element -> w.get().exchange())
.map(r -> r.bodyToMono(MyClass.class))
)
// subscribe to each response and throw received element further to the stream
.flatMap(response -> Mono.create(s -> response.subscribe(s::success)))
.window(1000) // batch of 1000 is ready
.flatMap(flow -> flow
.flatMap(element -> w.get().exchange())
.map(r -> r.bodyToMono(MyClass.class))
)
.flatMap(response -> Mono.create(s -> response.subscribe(s::success)));
}
public static class MyClass {
public Integer i;
}
UPDATE:
I've prepared a small application to reproduce your case. You can find it in my repository.
I have a .Net console application that is supposed to be long running and continous , basically 24 hours a day. It's for a rabbitmq consumer client. I am opening 30 channels on 1 connection, and each channel is responsible for 7 different queues.
Task creation:
tokenSource2 = new CancellationTokenSource();
cancellationToken = tokenSource2.Token;
for (int i = 0; i < 30; i++) //MAX 100 MODEL
{
List<string> partlist = tmpDBList.Take(7).ToList();
tmpDBList = tmpDBList.Except(partlist).ToList();
new Task(delegate { StartConsuming(partlist, cancellationToken); }, cancellationToken, TaskCreationOptions.LongRunning).Start();
}
The consumer method:
internal void StartConsuming(List<string> dbNames, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
using (IModel channel = Consumer.CreateModel())
{
foreach (string item in dbNames)
{
//Queue creation, exchange declare, bind, + basic eventhandler etc..
channel.BasicConsume(queue: item,
autoAck: true,
consumer: consumerEvent);
}
cancellationToken.ThrowIfCancellationRequested();
while (!cancellationToken.IsCancellationRequested)
{
cancellationToken.WaitHandle.WaitOne(5000);
}
}
}
Since I want the task to never stop I have the endless while cycle at the end of the using statement, otherwise the task stops, and the channels are disposed.
while (!cancellationToken.IsCancellationRequested)
{
cancellationToken.WaitHandle.WaitOne(5000);
}
Is this a an optimal solution?
Furthermore, each consumer event handler creates a DbContext of a specific database inside the
EventingBasicConsumer consumerEvent = new EventingBasicConsumer(channel);
consumerEvent.Received += (sender, basicDeliveryEventArgs) =>
{
cancellationToken.ThrowIfCancellationRequested();
//dbContext creation
}
event handler. Will the memory be freed after the eventhandler is finished ? Do I need to Dispose of the dbcontext and each class I am using inside the eventhandler?
How do I close a stage in JavaFX 2 after some specific external event has occurred? Suppose I have a stage with a simple progress bar that is filled up by a Task (borrowed from another answer):
Task<Void> task = new Task<Void>(){
#Override
public Void call(){
for (int i = 1; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
updateProgress(i, 10);
}
return null;
}
};
How do I close the window automatically (and open the next one) after the Task is done and the ProgressBar is filled to 100%?
Before return null; you can add
Platform.runLater(
new Runnable() {
public void run() {
stage.close();
}
}
);
or
progressBar.progressProperty().addListener(new ChangeListener<Number>(){
//add checking, that progress is >= 1.0 - epsilon
//and call stage.close();
})
The first is better. But note, that task is done on a separate thread. so you should put a request on stage.close() on JFX thread using special call.
Also, jewelsea provides links on stage closing questions in comment to the question.
WaitHandle.WaitAll throws a NotSupportedException when executed on Windows Phone (7.1). Is there an alternative to this method?
Here's my scenario: I am firing off a bunch of http web requests and I want to wait for all of them to return before I can continue. I want to make sure that if the user has to wait for more than X seconds (in total) for all of these requests to return, the operation should be aborted.
You can try with a global lock.
Start a new thread, and use a lock to block the caller thread, with the timeout value you want.
In the new thread, loop on the handles and call wait on each. When the loop is done, signal the lock.
Something like:
private WaitHandle[] handles;
private void MainMethod()
{
// Start a bunch of requests and store the waithandles in the this.handles array
// ...
var mutex = new ManualResetEvent(false);
var waitingThread = new Thread(this.WaitLoop);
waitingThread.Start(mutex);
mutex.WaitOne(2000); // Wait with timeout
}
private void WaitLoop(object state)
{
var mutex = (ManualResetEvent)state;
for (int i = 0; i < handles.Length; i++)
{
handles[i].WaitOne();
}
mutex.Set();
}
Another version using Thread.Join instead of a shared lock:
private void MainMethod()
{
WaitHandle[] handles;
// Start a bunch of requests and store the waithandles in the handles array
// ...
var waitingThread = new Thread(this.WaitLoop);
waitingThread.Start(handles);
waitingThread.Join(2000); // Wait with timeout
}
private void WaitLoop(object state)
{
var handles = (WaitHandle[])state;
for (int i = 0; i < handles.Length; i++)
{
handles[i].WaitOne();
}
}
The following code is adapted from an example in Real-Time Java Platform Programming by Peter C. Dibble:
import javax.realtime.*;
public class OSTimer {
static volatile boolean cont = true;
public static void main(String[] args) {
AsyncEventHandler handler = new AsyncEventHandler(){
public void handleAsyncEvent() {
System.out.println("Stopping...");
cont = false;
}
}
};
OneShotTimer timer = new OneShotTimer(new RelativeTime(3000, 0), handler);
timer.start();
while(cont){
System.out.println("Running");
if (timer.isRunning()) System.out.println("Timer is running");
try {
Thread.sleep(1000);
} catch(Exception e) { }
}
System.exit(0);
}
The the program is supposed to run for 3 seconds and then exit. However, the output shows that while the timer did indeed stop after 3 seconds, the program continues as usual, i.e. output is:
Running
Timer is running
Running
Timer is running
Running
Timer is running
Running
Running
Running......
Clearly the handler did not fire, and I've no idea why. Another example program involving a periodic timer triggering the handler does work as expected. The program structure is almost the same as the one here.
A few things to try:
Call fire() explicitly on the timer instance to see if you can force things
Try creating your handler by passing in the logic as a Runnable object to the handler. The API is a little unclear on this, but this is how I have specified handlers in the past.
Example:
AsyncEventHandler handler = new AsyncEventHandler(new Runnable() {
public void run() {
System.out.println("Stopping...");
cont = false;
}
});