Reactor 3 Emitter/Subscriber paralllel - java

i'm new in Reactive programming and have a lot of questions.
I think it is not a lack of examples or documentation it is just my understanding is wrong.
I'm trying to emulate slow subscriber;
Here is the code example
Flux.create(sink -> {
int i = 0;
while (true) {
try {
System.out.println("Sleep for " + MILLIS);
Thread.sleep(MILLIS);
int it = i++;
System.out.println("Back to work, iterator " + it);
sink.next(it);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).subscribeOn(Schedulers.elastic())
.subscribe(x -> {
try {
System.out.println("Value: " + x + ", Thread: " + Thread.currentThread().toString());
Thread.sleep(MILLIS + 4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System out is
Sleep for 1000
Back to work, iterator 0
Value: 0, Thread: Thread[elastic-2,5,main]
Sleep for 1000
Back to work, iterator 1
Value: 1, Thread: Thread[elastic-2,5,main]
Sleep for 1000
Back to work, iterator 2
Value: 2, Thread: Thread[elastic-2,5,main]
I thought if subscriber is slow, i should see more threads due to Schedulers.elastic()
Also i tried to make publishOn() and it seems like i make it async, but still couldn't handle result in several threads.
Thanks for comments and answers.

If you want it to run in diferent threads you need to use .parallel() like this and the emit will be don in different thread
Flux.create(sink -> {
int i = 0;
while (true) {
try {
System.out.println("Sleep for " + MILLIS);
Thread.sleep(100);
int it = i++;
System.out.println("Back to work, iterator " + it);
sink.next("a");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
})
.parallel()
.runOn(Schedulers.elastic())
.subscribe(x -> {
try {
System.out.println("Value: " + x + ", Thread: " + Thread.currentThread().toString());
Thread.sleep(100 + 4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
})
;
}

Related

java multi threading executor never shutdown threads

Could some one take a look this below program ?.
It is working fine for small process, but not exiting the program after completing large process.
Note: If it is small size query, about 50 records (retrieving and updating), the program is Exiting normally....
The purpose of this program is to get the data from the database, go to cloud to read JSON, validate the data and update the record in database with result.
public class ThreadLauncher
{
public static void main(String args[])
{
final ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); // or hardcode a number
List<Future<Runnable>> futures = new ArrayList<Future<Runnable>>();
for (int n = 0; n < 10; n++)
{
Future f = service.submit(new Task(n));
futures.add(f);
}
// wait for all tasks to complete before continuing
for (Future<Runnable> f : futures)
{
try {
f.get();
//shut down the executor service so that this thread can exit
} catch (InterruptedException e) {
System.out.println("Exiting with InterruptedException : " + e.getMessage());
e.printStackTrace();
} catch (ExecutionException e) {
System.out.println("Exiting with ExecutionException : " + e.getMessage());
e.printStackTrace();
}
}
service.shutdownNow();
System.out.println("Exiting normally...");
}
}
final class Task
implements Runnable
{
private int loopCounter;
private int totalLoops = 5;
public Task(int counter)
{
this.loopCounter = counter;
}
#Override
public void run()
{
try {
GCPJSON.getInstance().getGCPDataFromJSON(PRODDataAccess.getInstance().getDataToProcess(loopCounter,totalLoops));
System.out.println("Task ID : " + this.loopCounter + " performed by " +
Thread.currentThread().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is my updated code.I have changed it from Future to FutureTask and added few lines items. I am hoping all these 10 tasks run in parallel.
List<FutureTask<Runnable>> futures = new ArrayList<FutureTask<Runnable>>();
for (int n = 0; n < 10; n++)
{
FutureTask f = (FutureTask) service.submit(new Task(n));
futures.add(f);
}
// wait for all tasks to complete before continuing
// for (FutureTask<Runnable> f : futures)
for (int i=0; i< futures.size(); i++)
{
FutureTask f = (FutureTask)futures.get(i) ;
//System.out.println("Number of futureTasks: " + i);
try {
if(!f.isDone()){
//wait indefinitely for future task to complete
f.get();
//System.out.println("FutureTask output="+f.get());
}else{
System.out.println("Task number :" + i + "Done.");
}
} catch (InterruptedException | ExecutionException e) {
System.out.println("Exiting with InterruptedException : " + e.getMessage());
e.printStackTrace();
}
}
//If we come out from the loop, we must have completed all the tasks. e.e. In above case , 10 tasks ( 10 loop submites)
try {
if (!service.awaitTermination(10000000, TimeUnit.MICROSECONDS)) {
System.out.println("Exiting normally...");
service.shutdownNow();
System.exit(0);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
if(!service.isShutdown()){
System.exit(0);
}
It's because when you call shutdown or shutdownNow on executorService it only try to stop active threads and it will return list of active tasks based on Java documentation:
Attempts to stop all actively executing tasks, halts the processing of
waiting tasks, and returns a list of the tasks that were awaiting
execution.
This method does not wait for actively executing tasks to terminate.
Use {awaitTermination} to do that.
As documentation says you need to call awaitTermination to make sure every thread has finished or this method will kill them at the end of timeout.
UPDATE:
If you have no idea about timing estimation you can add following lines to make sure that all threads have been finished successfully.
int filesCount = getFileCount();//you know the files count, right?
AtomicInteger finishedFiles = new AtomicInteger(0);
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < threadCount; i++)
executorService.submit(() -> {
//do you work
//at the end of each file process
finishedFiles.incrementAndGet();
}
while (finishedFiles.get() < filesCount) { //let's wait until all files have been processed
Thread.sleep(100);
}
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.MINUTES);//anyway they already should have finished

Selenium method visibilityOf - Doesn't seem to be working?

When i used the listed method to see whether an element is visible on the page, I get an exception stating that its unable to locate an element using the specified locator.
Any ideas, has anyone faced this issue before or even have a better method?
public boolean isElementPresentByWebElement(WebElement element) {
Wait<WebDriver> fluentWait = new FluentWait<WebDriver>(driver).withTimeout(15, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
for (int i = 0; i < 2; i++) {
try {
fluentWait.until(ExpectedConditions.visibilityOf(element));
System.out.println("Element is visible: " + element.toString());
return true;
} catch (Exception e) {
System.out.println(
"Unable to locate the element: " + element.toString() + ", Exception: " + e.toString());
throw (e);
}
}
return false;
}
I think your code is overly complicated for what you are trying to do. There is a built in class, ExpectedConditions, that will do what you want. You are also looping over the wait which is unnecessary. I would suggest that you pass in a locator (By) instead of a WebElement. It will expand your ability to use this function because you won't have to find the element before using the function.
public boolean isElementPresentByLocator(By locator)
{
try
{
new WebDriverWait(driver, 15).until(ExpectedConditions.visibilityOfElementLocated(locator));
System.out.println("Element is visible: " + locator.toString());
return true;
}
catch (TimeoutException e)
{
System.out.println("Unable to locate the element: " + locator.toString() + ", Exception: " + e.toString());
return false;
}
}
The code below is more of a direct translation and simplification of your code.
public boolean isElementPresentByWebElement(WebElement element)
{
try
{
new WebDriverWait(driver, 15).until(ExpectedConditions.visibilityOf(element));
System.out.println("Element is visible: " + element.toString());
return true;
}
catch (TimeoutException e)
{
System.out.println("Unable to locate the element: " + element.toString() + ", Exception: " + e.toString());
return false;
}
}
Updated :
try using following :
int waitCounter = 0;
public static void WaitUntilVisible(WebDriver driver, WebElement element) throws InterruptedException, IOException {
try {
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.visibilityOf(elementToBeClicked));
if (!elementToBeClicked.isDisplayed()) {
System.out.println("Element not visible yet. waiting some more for " + element);
if (waitCounter < 3) {
waitCounter++;
WaitUntilVisible(element);
}
waitCounter = 0;
}
} catch (Exception e)
{
System.out.println("Handling exception");
}
}

Locking access to another class, from run method

fairly complex code but it's a very simple issue.
I have a thread, this is its run method:
public void run() //gets pages and writes to them
{ // i printed the pageId of every process to check they are running at the same time and competing for resources
for(ProcessCycle currentCycle : processCycles.getProcessCycles())
{
Long[] longArray = new Long[currentCycle.getPages().size()];
try {
Page<byte[]>[] newPages = mmu.getPages(currentCycle.getPages().toArray(longArray));
for(int i = 0; i < newPages.length; i++)
{
MMULogger.getInstance().write("GP:P" + id + " " + currentCycle.getPages().get(i) + " " + Arrays.toString(currentCycle.getData().get(i)), Level.INFO);
}
List<byte[]> currentPageData = currentCycle.getData();
System.out.println("process id " + id);
for(int i = 0; i < newPages.length;i++)
{
byte[] currentData = currentPageData.get(i);
newPages[i].setContent(currentData);
}
Thread.sleep(currentCycle.getSleepMs());
} catch (ClassNotFoundException | IOException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
don't bother reading all of it. just notice that after the mmu.getpages there is a for loop.
While a process is inside the for loop, i want to lock access to mmu.getpages for all other threads. synchronized is no good since my original process is no longer in mmu, but in the for loop, and reentrantlock might be a good idea but I'm unfamiliar with the syntax and ran into some issues.
long story short - how do i make all other threads wait while some thread is inside the for loop after mmu.getpages?
Usually I chose an approach like this:
private Object lock = new Object();
public void run() //gets pages and writes to them
{ // i printed the pageId of every process to check they are running at the same time and competing for resources
for(ProcessCycle currentCycle : processCycles.getProcessCycles())
{
Long[] longArray = new Long[currentCycle.getPages().size()];
try {
synchrnonized(lock) {
Page<byte[]>[] newPages = mmu.getPages(currentCycle.getPages().toArray(longArray));
for(int i = 0; i < newPages.length; i++)
{
MMULogger.getInstance().write("GP:P" + id + " " + currentCycle.getPages().get(i) + " " + Arrays.toString(currentCycle.getData().get(i)), Level.INFO);
}
}
List<byte[]> currentPageData = currentCycle.getData();
System.out.println("process id " + id);
for(int i = 0; i < newPages.length;i++)
{
byte[] currentData = currentPageData.get(i);
newPages[i].setContent(currentData);
}
Thread.sleep(currentCycle.getSleepMs());
} catch (ClassNotFoundException | IOException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Not sure if there is a better way. This will only work as expected when all threads share the same instance of this object, otherwise you have to make lock a static member variable.
In my opinion a ReadWriteLock might be a best approach.
Something like this:
public class MmuClass {
private ReadWriteLock blockGetPages = new ReentrantReadWriteLock();
public byte [] getPages(...) {
try{
blockGetPages.readLock().lock();
// ...
// ...
// ...
return result;
finally{
blockGetPages.readLock().unlock();
}
}
public void lockAccessToGetPages(){
blockGetPages.writeLock().lock();
}
public void unlockAccessToGetPages(){
blockGetPages.writeLock().unlock();
}
}
and
Page<byte[]>[] newPages = mmu.getPages(currentCycle.getPages().toArray(longArray));
try{
mmu.lockAccessToGetPages();
for(int i = 0; i < newPages.length; i++) {
MMULogger.getInstance().write("GP:P" + id + " " + currentCycle.getPages().get(i) + " " + Arrays.toString(currentCycle.getData().get(i)), Level.INFO);
}
} finally{
mmu.unlockAccessToGetPages();
}
In this solutions all "readers" can simultaneously call getPages(), the access is blocked after calling lockAccessToGetPages() and unblocked after calling unlockAccessToGetPages(). If one thread locks the object in write mode, only this thread has access to the method. If some thread tries to lock it in write mode, must wait until all readers, which are currently "inside" the metod, finish their fork and leave the method.

Error removing user from ClientHandler

I have an error when a client closes the connection from the socket. What is supposed to happen is that the user closes their client, the server then receives this and should decrement the users who are connected which is stored in a relative integer value. However I receive an error relating to the for loop on the remove a user function.
public synchronized void removeUsers(Socket client,int clientUser)
{
int index=0;
for (ClientHandler newHandler:userList)
{
if(newHandler.getUserId() == clientUser)
{
try
{
client.close();
Thread.currentThread().isInterrupted();
userList.remove(index);
}
catch (IOException e)
{
System.out.println("Unable to disconnect!");
System.exit(1);
}
}
index++;
}
}
Client handler run:
public void run()
{
String message;
message = input.nextLine(); //Note method!
getMessage(message);
System.out.println(message.substring(0, count+1)+"-"+message.substring(count+1));
while (!message.substring(0, count+1).equals("***CLOSE***"))
{
if(message.equals(user.getItemName(1)+"$status$")|| //checks for status of Ball
message.equals(user.getItemName(2)+"$status$"))
{
if (user.BidItem(user.getItemName(1)))
{
System.out.println("Top bid for " + //posts for server
message.substring(0, count+1) + " is: "
+ user.getTopBid(message.substring(0, count+1)));
output.println("Top bid for " + //posts for client
message.substring(0, count+1) + " is: "
+ user.getTopBid(message.substring(0, count+1))
+ " by User" +
user.getTopBidder(message.substring(0, count+1)));
}
else
{
System.out.println("-1");
output.println("-1");
}
}
else
{
if(user.BidItem(message.substring(count+2))) //same but now for Plate
{
if(user.isGrtrThanTopBid(message.substring(count+2),
Double.parseDouble(message.substring(0, count+1))))
{
user.setTopBid(message.substring(count+2),
Double.parseDouble(message.substring(0, count+1)), clientUser);
System.out.println("Bid Accepted for " + message.substring(count+2));
output.println("Bid Accepted for " + message.substring(count+2));
}
else
{
System.out.println("Low bid for " + message.substring(count+2));
output.println("Low bid for " + message.substring(count+2));
}
}
else
{
System.out.println("Late bid for " + message.substring(count+2));
output.println("Late bid for " + message.substring(count+2));
}
}
message = input.nextLine();
count = 0;
getMessage(message);
}
output.println(" messages received.");
System.out.println("\n* Closing connection... *");
user.removeUsers(client,clientUser);
}
The full error is here:
Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at Users.removeUsers(AuctionServer.java:211) //Relates to top of for loop
at ClientHandler.run(AuctionServer.java:435)
You can't remove objects from lists when you iterates on them.
Try this.
Instead use a queue.
Queue queue = new LinkedList<Client>();
int index=0;
for (ClientHandler newHandler:userList)
{
if(newHandler.getUserId() == clientUser)
{
try
{
client.close();
Thread.currentThread().isInterrupted();
queue.add(userList.get(index));
}
catch (IOException e)
{
System.out.println("Unable to disconnect!");
System.exit(1);
}
}
index++;
}
while(!queue.isEmpty()) {
userList.remove(queue.remove());
}

timer in java using threads

I am developing an exam software in core java where I am conducting various tests for students.I am stuck at a piece of code where timer with countdown is set.
My problem is when I display minutes its working fine but when I try to display seconds with the minutes in mm:ss format its not working.
Code is:
// for below int ti=20,si=60;
// test is for 20 minutes
public void run() {
while (true) {
try {
Thread.currentThread().sleep(60000);
for (int i = 0; i <= 60; i++) {
etime.setText("Remaining Time:-" + ti + ":" + si);
System.out.println("Remaining Time:-" + ti + ":" + si);
Thread.currentThread().sleep(1000);
si--;
}
ti--;
if (ti == 0) {
close();
}
} catch (InterruptedException ex) {
Logger.getLogger(Exam.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Once si has counted down to 0, you need to reset it to 59.
Also, the i variable is completely unnecessary, and there is an off-by-one error in your loop.

Categories