Basis a condition in my Observable, I want to delay onNext / onError. My code is as follows:
fun check3(){
val list = arrayListOf(1,2,3,4,5,6,7, null)
val obs = Observable.create<Int> { subscriber ->
list.filter {
it != null
}.map {
if (it!! %2 == 0 ) {
Thread.sleep(3000)
subscriber.onError(IllegalArgumentException("Mod is true"))
} else {
subscriber.onNext(it)
subscriber.onComplete()
}
}
}
}
A sore here being Thread.sleep(3000)
Is there a better way of doing this? Basically I want to delay the onError notification to my subscriber if the if(it %2) condition is met
You can use concatMap to turn the sleep into a non-blocking delay:
Observable.fromIterable(list.filter { it != null })
.concatMap {
if (it!! % 2 == 0) {
return#concatMap Observable.error(IllegalArgumentException("Mod is true"))
.delay(3, TimeUnit.SECONDS, true)
}
Observable.just(it)
}
.take(1)
Related
So we recently started coding in college and I'm having trouble with my game in Greenfoot. I should normally be able to collect 5 coins on level 1, go to the door, and progress to level 2 and so on... This is my piece of code so far:
private void collect () {
Actor coin = getOneIntersectingObject(Coin.class);
if (coin != null) {
getWorld().removeObject(coin);
coinsCollected++;
}
if (coinsCollected == 5 && fiveCoinsLevel1 == false) {
if (this.getWorld().getClass() == Level_1.class) {
getWorld().addObject(new door_temp(), 157, 162);
fiveCoinsLevel1 = true;
secondLevel();
coinsCollected = 0;
}
}
if (coinsCollected == 5 && fiveCoinsLevel2 == false && fiveCoinsLevel1 == true) {
if (this.getWorld().getClass() == Level_2.class) {
getWorld().addObject(new door_temp(), 157, 162);
fiveCoinsLevel2 = true;
thirdLevel();
}
}
}
After that I have two methods that set the world to either level 2 or 3:
public void secondLevel () {
Actor secondlvl = getOneIntersectingObject(door_temp.class);
if (secondlvl != null) {
Greenfoot.setWorld(new Level_2());
}
}
public void thirdLevel () {
Actor thirdlvl = getOneIntersectingObject(door_temp.class);
if (thirdlvl != null) {
Greenfoot.setWorld(new Level_3());
}
}
Now for some reason, once I collect all 5 coins on level 1 and reach the door to go to level 2, it sends me straight to level 3.
Thanks to anyone who can help me :)
I'm little confused with tasks in Java multithreading.
Namely, I've 15 objects, which implements Callable and i'm submitting it by ExecutorService. Each Callable has its own progress bar with is updating in for loop with setProgress method.
I want to show 3 of 15 callables which will finish their job in first, second and third position by getting their names and setting it to labels on my scene. Of course each callable has different working time.
I created Task and i'm starting it in new thread and iterating over list of future tasks from my ExecutorService.
The problem is that my labels aren't visible until first element of the future list is true (until first thread is finished). I have really no idea why and i would be very grateful for your help.
public void startButtonClicked() {
Task task = new Task<Void>() {
#Override
public Void call() {
int i = 0;
while (i < 3) {
for (Future<Boolean> future : futures) {
try {
if (future.get() == true && i == 0) {
labelFirst.setVisible(true);
i++;
}
if (future.get() == true && i == 1) {
labelSecond.setVisible(true);
i++;
}
if (future.get() == true && i == 2) {
labelThird.setVisible(true);
i++;
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
return null;
}
};
for (Callable c : callables) {
futures.add(executorService.submit(c));
}
new Thread(task).start();
executorService.shutdown();
}
In my ideal solution each label will become visible when their callable will finish, so labelSecond should appear some time after labelFirst.
It's my call method in my callable:
public Boolean call() {
double raceTime = ThreadLocalRandom.current().nextDouble(45.0, 60.0);
try {
for (double i = 0; i < raceTime; i += 0.01) {
TimeUnit.MILLISECONDS.sleep(1);
progressBar.setProgress(i / raceTime);
}
} catch (ParseException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
EDIT:
With checking future.isDone() and little changes it works as i wished.
public void startButtonClicked() {
Task task = new Task<Void>() {
#Override
public Void call() {
int i = 0;
while (i < 3) {
i = 0;
for (Future<Boolean> future : futures) {
if (future.isDone() == true) i++;
if (i == 1) {
labelFirst.setVisible(true);
labelFirstCyclistName.setVisible(true);
}
if (i == 2) {
labelSecond.setVisible(true);
labelSecondCyclistName.setVisible(true);
}
if (i == 3) {
labelThird.setVisible(true);
labelThirdCyclistName.setVisible(true);
}
}
}
return null;
}
};
for (Cyclist c : cyclists) {
futures.add(executorService.submit(c));
}
new Thread(task).start();
executorService.shutdown();
}
The problem is that my labels aren't visible until first element of
the future list is true (until first thread is finished). I have
really no idea why and i would be very grateful for your help.
According to the documentation of Future#get
Waits if necessary for the computation to complete, and then retrieves
its result.
Here is your code - pay special attention to a line containing future.get():
public Void call() {
int i = 0;
while (i < 3) {
for (Future<Boolean> future : futures) {
try {
if (future.get() == true && i == 0) {
During the first iteration of the loop the first future is retrieved from futures, and then future.get() stops the execution of the loop and waits (holds) until execution of this first future (the first thread) will finish and will return a result.
Then the loop continues and LabelX..setVisible(true); are called making labels visible.
I have a PublishSubject with this configuration:
PublishSubject<Message> messageObserver =
messageObserver
.filter(t -> test(t))
.buffer(eventsSaveTimeSpanInSeconds, TimeUnit.SECONDS, eventsSaveCount)
.subscribe(messages -> saveToDB(messages));
Different threads of my application are writing messages to this PublishSubject via onNext().
As I see, the buffer underlying ObservableBufferTimed.BufferExactBoundedObserver is non thread-safe, because its onNext looks as follows:
public void onNext(T t) {
U b;
synchronized (this) {
b = buffer;
if (b == null) {
return;
}
b.add(t);
if (b.size() < maxSize) {
return;
}
buffer = null;
producerIndex++;
}
if (restartTimerOnMaxSize) {
timer.dispose();
}
fastPathOrderedEmit(b, false, this);
try {
b = ObjectHelper.requireNonNull(bufferSupplier.call(), "The buffer supplied is null");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
actual.onError(e);
dispose();
return;
}
synchronized (this) {
buffer = b;
consumerIndex++;
}
if (restartTimerOnMaxSize) {
timer = w.schedulePeriodically(this, timespan, timespan, unit);
}
}
To make the race condition case more obvious I set the eventsSaveTimeSpanInSeconds and eventsSaveCountparams to 1 (1 event in 1 second).
The problem appears in this block:
synchronized (this) {
b = buffer;
if (b == null) {
return;
}
b.add(t);
if (b.size() < maxSize) {
return;
}
buffer = null;
producerIndex++;
}
So, if two messages are buffering at the same time then first message fills the buffer and assigns null to buffer variable. New buffer will be initialized later after the synchronized block. If there is a race condition, when the buffer is null, the second message will not buffered because of the code:
if (b == null) {
return;
}
Is this a defect or a corrrect buffer behavior? How can I avoid this situation?
Use a serialized subject if multiple threads want to call onNext:
Subject<Message> messageObserver = PublishSubject.<Message>create().toSerialized();
messageObserver
.filter(t -> test(t))
.buffer(eventsSaveTimeSpanInSeconds, TimeUnit.SECONDS, eventsSaveCount)
.subscribe(messages -> saveToDB(messages));
// from any thread now
messageObserver.onNext(message);
I glanced at execute method of ThreadPoolExecutor class. This seems to be very short and simple:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
}
}
But nothing seems to be happening if the the condition poolSize >= corePoolSize is satisfied!
Because of if the first part of a ORcondition is true, the second won't be executed:
if (true || anyMethodWillNotBeExecuted()) { ... }
According to the rules for thread creation, here also is maximumPoolSize. And in case if the number of threads is equal (or greater than) the corePoolSize and less than maxPoolSize the new thread should be created for task or task should be added to queue.
So why in case when poolSize greater than or equals to corePoolSize nothing should happen?..
addIfUnderCorePoolSize will create a new "core" thread for this executor.
If number of threads in the executor (poolSize) is already greater than or equal to number of "core" threads (corePoolSize), then obviously there is no need to create more "core" threads.
Maybe expanding OR condition will be a bit clearer:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
if (poolSize >= corePoolSize) {
// there are enough core threads
// let's try to put task on the queue
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
} else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
} else if (addIfUnderCorePoolSize(command)) {
// there was not enough core threads, so we started one
// the task is being executed on a new thread, so there's nothing else to be done here
return;
} else {
// there are enough core threads
// but we could not start a new thread
// so let's try to add it to the queue
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
} else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
}
}
I need to override execute method of executor where I need to change the behavior that threads more than core pool size will be created only when queue is full.
However in real time applications this behavior is undesirable as it can lead to unending wait of task present in queue.
I have changed the execute method as below:
public void execute(Runnable command)
{
System.out.println("ActiveCount : " + getActiveCount() + " PoolSize : " + getPoolSize()
+ " QueueSize : " + getQueue().size() +" Idle Threads : " +(getPoolSize()-getActiveCount()));
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
else if (isRunning(c) && workQueue.offer(command))
{
int recheck = ctl.get();
if (getActiveCount() < workerCountOf(recheck) && isRunning(recheck) && workQueue.offer(command)) {
return;
}
if (addWorker(command, false)) {
return;
}
else if (! isRunning(recheck) && remove(command))
{
reject(command);
}
else if (workerCountOf(recheck) == 0)
{
addWorker(null, false);
}
}
else
{
reject(command); // add task to the queue
}
}
Trying to achieve:
CoreThreads -> Non-CoreThreads -> Queue instead of CoreThreads -> Queue -> Non-CoreThreads.
I dont understand why you need to change execute method, I think, max pool size should not be preferred over queue, as I can see in you code.
I had same problem and you can follow the link :
click to follow the thread.
I feel this should be you last choice, try something else first.