EDIT: Ok, this is really stupid but I don't know why I didn't see it was a normal loop without the usual increments. I hope I was drunk when I posted this question because now I feel super idiot. Thanks anyway guys!
I'm following some tutorials on Java multi-threading in order to gather as much information and examples as possible.
On the Oracle website there is an official tutorial on Java Concurrency and I am looking at the Guarded Blocks section (here).
Whereas all the concepts are clear, I am reading the Producer/Consumer example at the bottom of the page and I do not understand some parts of the code.
Specifically, in the following is the code for the run() method of the Consumer class, where I do not understand how that for loop is supposed to work. It doesn't even look as it can work to me.
Can anyone explain me?
public void run() {
Random random = new Random();
for (String message = drop.take();
! message.equals("DONE");
message = drop.take()) {
System.out.format("MESSAGE RECEIVED: %s%n", message);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
}
It's just for loop being used in a non-idiomatic way.
You have the initialization String message = drop.take(); (instead of int i = 0;).
Then you have the test !message.equals("DONE"); (instead of i < 10).
Finally you have the "increment" or loop-advance or whatever the actual term is. Get the next value with message = drop.take(); (instead of i++).
Maybe it would be easier to understand when converted to a while-loop:
public void run() {
Random random = new Random();
String message = drop.take()
while (!message.equals("DONE")) {
System.out.format("MESSAGE RECEIVED: %s%n", message);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
message = drop.take()
}
}
Keep in mind that the for-loop generally consists of three parts:
for (INITIALIZATION; CONDITION; AFTERTHOUGHT)
{
// Code for the for-loop's body goes here.
}
INITIALIZATION is run once before the first iteration, CONDITION is checked prior to every iteration and AFTERTHOUGHT is executed after every iteration.
(Taken from https://en.wikipedia.org/wiki/For_loop#Traditional_for-loops)
So in this example, the INITIALIZATION of the for-loop creates the message variable and takes the first message from drop. It then checks it in the CONDITION block to see if its is anything but DONE. If it is, the loop body is executed once, printing the message and sleeping for up to 5000 milliseconds. Then the next message is taken in the AFTERTHOUGHT clause and the loops checks the CONDITION block again to either print the next message or leave the loop once it receives DONE.
Related
I made a switch case statement menu with one of the options being System.exit(0);. This is all surrounded by a try, finally that calls the method all of this is in. Would you guys not recommend this style of loop or am I all good?
public void Run() {
Scanner myObj = new Scanner(System.in);
int menuInput;
try {
System.out.println(" 1) call something\n"
+"2) quit");
menuInput = myObj.nextInt();
myObj.nextLine();
switch(menuInput) {
case 1:
something();
break;
case 2:
System.exit(0);
break;
}
}catch (Exeption e ){
System.out.println("Something went wrong.");
}finally{
Run();
}
}
No.
What you have here is an infinite recursion. Eventually you'd overflow the stack.
Use an actual loop instead:
while (true) {
try {
// ...
} catch (Exception e) {
// ...
}
}
And you almost never want to call System.exit. Just break the loop instead.
Is this legal code? Yes.
Is what you have there recommended? No.
If the method throws an exception it's likely recalling it will throw again. See the quote below.
Calling it again in a tight loop without attempting remedy, at least waiting a recovery and counting failures (3 strikes out?) will just end up in a tight loop of failure and stack overflow here.
So:
Can you identify errors that retrying may work and only retry on those?
You should almost certainly include some kind of 'back-off' wait before retry.
Always (always!) include a maximum retry number after which you accept failure.
In my experience the only kind of failure that may work on retry is 'service unavailable' meaning an intermittent outage.
It may not be relevant, but things like (say) invalid credentials aren't going to fix themselves and ideally you don't resubmit those. That's particularly because you end up locking the account and being in an even worse state and possibly causing issues for others using the valid credential...
The other scenario is (say) file not found and you're using the non-existence of a file as a way of polling for something.
That's a poor design pattern and is a misuse of exception handling.
You should strongly prefer to use some kind for existence check in those cases and not let routine activity get confused with exception handling of issues.
Also if you do retry log each attempt (it may be useful later to see whether things are running smoothly or getting delayed in retry scenarios even if the go through eventually). But always differentiate a 'Warning' when retrying and 'Error' when 'throwing in the towel' and failing.
public class Runner {
private static int MAX_RETRIES=3;
private static int BACK_OFF_MILLIS=30000;
public void Run() throws Exception,InterruptedException {
final int TRIES=3;//In reality may be configured.
int trycount=1;
for(;;){
try{
tryRun();
return;
}catch(Exception e){
String message=e.getMessage();
if(trycount>=MAX_RETRIES){
System.out.println("*FAILED*: "+e.getMessage());
throw e;
}
boolean retriable=true;
//Any tests for non-retriable exceptions here...
if(!retriable){
System.out.println("*FAILED*: non-retriable exception - "+e.getMessage());
throw e;
}
++trycount;
System.out.println("Warning: "+e.getMessage()+" retrying "+ trycount+" of "+TRIES);
try {
Thread.sleep(trycount*BACK_OFF_MILLIS);//Some kind of back-off...
}catch(InterruptedException ie){
System.out.println("*FAILED*: Interrupted. Aborting.");
throw ie;
}
continue;
}
}
}
public void tryRun() throws Exception{
//Real workload goes here!
}
}
NB: The back-off strategy here is very simplistic. When it comes to outages then it's usually recommended to implement a random element and an increasing back-off like 1 minute, 10 minutes, 25 minutes. But that's a topic in itself.
I'm not sure who really said but this popular quote seems relevant.
The definition of insanity is doing the same thing over and over again
and expecting different results
I was about to write something about this, but maybe it is better to have a second opinion before appearing like a fool...
So the idea in the next piece of code (android's room package v2.4.1, RoomTrackingLiveData), is that the winner thread is kept alive, and is forced to check for contention that may have entered the process (coming from losing threads) while computing.
While fail CAS operations performed by these losing threads keep them out from entering and executing code, preventing repeating signals (mComputeFunction.call() OR postValue()).
final Runnable mRefreshRunnable = new Runnable() {
#WorkerThread
#Override
public void run() {
if (mRegisteredObserver.compareAndSet(false, true)) {
mDatabase.getInvalidationTracker().addWeakObserver(mObserver);
}
boolean computed;
do {
computed = false;
if (mComputing.compareAndSet(false, true)) {
try {
T value = null;
while (mInvalid.compareAndSet(true, false)) {
computed = true;
try {
value = mComputeFunction.call();
} catch (Exception e) {
throw new RuntimeException("Exception while computing database"
+ " live data.", e);
}
}
if (computed) {
postValue(value);
}
} finally {
mComputing.set(false);
}
}
} while (computed && mInvalid.get());
}
};
final Runnable mInvalidationRunnable = new Runnable() {
#MainThread
#Override
public void run() {
boolean isActive = hasActiveObservers();
if (mInvalid.compareAndSet(false, true)) {
if (isActive) {
getQueryExecutor().execute(mRefreshRunnable);
}
}
}
};
The most obvious thing here is that atomics are being used for everything they are not good at:
Identifying losers and ignoring winners (what reactive patterns need).
AND a happens once behavior, performed by the loser thread.
So this is completely counter intuitive to what atomics are able to achieve, since they are extremely good at defining winners, AND anything that requires a "happens once" becomes impossible to ensure state consistency (the last one is suitable to start a philosophical debate about concurrency, and I will definitely agree with any conclusion).
If atomics are used as: "Contention checkers" and "Contention blockers" then we can implement the exact principle with a volatile check of an atomic reference after a successful CAS.
And checking this volatile against the snapshot/witness during every other step of the process.
private final AtomicInteger invalidationCount = new AtomicInteger();
private final IntFunction<Runnable> invalidationRunnableFun = invalidationVersion -> (Runnable) () -> {
if (invalidationVersion != invalidationCount.get()) return;
try {
T value = computeFunction.call();
if (invalidationVersion != invalidationCount.get()) return; //In case computation takes too long...
postValue(value);
} catch (Exception e) {
e.printStackTrace();
}
};
getQueryExecutor().execute(invalidationRunnableFun.apply(invalidationCount.incrementAndGet()));
In this case, each thread is left with the individual responsibility of checking their position in the contention lane, if their position moved and is not at the front anymore, it means that a new thread entered the process, and they should stop further processing.
This alternative is so laughably simple that my first question is:
Why didn't they do it like this?
Maybe my solution has a flaw... but the thing about the first alternative (the nested spin-lock) is that it follows the idea that an atomic CAS operation cannot be verified a second time, and that a verification can only be achieved with a cmpxchg process.... which is... false.
It also follows the common (but wrong) believe that what you define after a successful CAS is the sacred word of GOD... as I've seen code seldom check for concurrency issues once they enter the if body.
if (mInvalid.compareAndSet(false, true)) {
// Ummm... yes... mInvalid is still true...
// Let's use a second atomicReference just in case...
}
It also follows common code conventions that involve "double-<enter something>" in concurrency scenarios.
So only because the first code follows those ideas, is that I am inclined to believe that my solution is a valid and better alternative.
Even though there is an argument in favor of the "nested spin-lock" option, but does not hold up much:
The first alternative is "safer" precisely because it is SLOWER, so it has MORE time to identify contention at the end of the current of incoming threads.
BUT is not even 100% safe because of the "happens once" thing that is impossible to ensure.
There is also a behavior with the code, that, when it reaches the end of a continuos flow of incoming threads, 2 signals are dispatched one after the other, the second to last one, and then the last one.
But IF it is safer because it is slower, wouldn't that defeat the goal of using atomics, since their usage is supposed to be with the aim of being a better performance alternative in the first place?
I am at a loss. I have a BlockingDeque
private class Consumer extends Thread {
#Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
if (connection.isReady()) {
final Item item = queue.takeFirst();
try {
ListenableFuture<Result> listenableFuture = connection.submitItem(item);
Futures.addCallback(listenableFuture, new FutureCallBackImpl<Result>(item));
} catch (RejectedExecutionException e) {
LOGGER.debug("Slow down submission of tasks we have a queue full in connection");
queue.addFirst(item);
}
}
}
} catch (InterruptedException e) {
LOGGER.debug("Interrupted. I will not propagate up because I own this thread");
}
}
}
This code normally blocks at queue.takeFirst() when no items are in the queue. However, it does not unblock once I add the item as expected. While debugging I can see the items being in the queue and also when I stop Tomcat I serialize the queue. Upon starting it I de-serialize the queue and at that point the queue.takeFirst() retrieves the item (the same that previously did not retrieve) and submits it.
Does anyone have any ideas?
EDIT
To stress my point a bit more. If I change the queue.takeFirst() with a queue.pollFirst() and adjust the code slightly to ignore passes that yield null items then the code works as expected.
Perhaps your code don't enter the if because connection.isReady() returns false.
Check it to be sure that it really stops waiting for the first item in the queue.
So Let me explain why this piece of code will not work when items are added to the queue next time (i.e. after it dequeued all the elements first)
When the queue becomes empty for the first time, the call to this code final Item item = queue.takeFirst(); will throw InterruptedException, which is getting caught by code outside while loop, so the code will never return to the while loop again. Putting first try block inside while loop will resolve the first issue.
Secondly, it needed to call Thread.currentThread().interrupted() inside catch block to pass the while condition next time so that it is ready to read for future element addition into queue. Infact I didn't understand the reason for calling this line of code while (!Thread.currentThread().isInterrupted()).
Currently I am writing interesting blog for BlockingDeque (WIP), soon you will find more information at my blog http://singletonjava.blogspot.com
The question has been posted before but no real example was provided that works. So Brian mentions that under certain conditions the AssertionError can occur in the following code:
public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n!=n)
throw new AssertionError("This statement is false");
}
}
When holder is improperly published like this:
class someClass {
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
}
I understand that this would occur when the reference to holder is made visible before the instance variable of the object holder is made visible to another thread. So I made the following example to provoke this behavior and thus the AssertionError with the following class:
public class Publish {
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
public static void main(String[] args) {
Publish publish = new Publish();
Thread t1 = new Thread(new Runnable() {
public void run() {
for(int i = 0; i < Integer.MAX_VALUE; i++) {
publish.initialize();
}
System.out.println("initialize thread finished");
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
int nullPointerHits = 0;
int assertionErrors = 0;
while(t1.isAlive()) {
try {
publish.holder.assertSanity();
} catch(NullPointerException exc) {
nullPointerHits++;
} catch(AssertionError err) {
assertionErrors ++;
}
}
System.out.println("Nullpointerhits: " + nullPointerHits);
System.out.println("Assertion errors: " + assertionErrors);
}
});
t1.start();
t2.start();
}
}
No matter how many times I run the code, the AssertionError never occurs. So for me there are several options:
The jvm implementation (in my case Oracle's 1.8.0.20) enforces that the invariants set during construction of an object are visible to all threads.
The book is wrong, which I would doubt as the author is Brian Goetz ... nuf said
I'm doing something wrong in my code above
So the questions I have:
- Did someone ever provoke this kind of AssertionError successfully? With what code then?
- Why isn't my code provoking the AssertionError?
Your program is not properly synchronized, as that term is defined by the Java Memory Model.
That does not, however, mean that any particular run will exhibit the assertion failure you are looking for, nor that you necessarily can expect ever to see that failure. It may be that your particular VM just happens to handle that particular program in a way that turns out never to expose that synchronization failure. Or it may turn out the although susceptible to failure, the likelihood is remote.
And no, your test does not provide any justification for writing code that fails to be properly synchronized in this particular way. You cannot generalize from these observations.
You are looking for a very rare condition. Even if the code reads an unintialized n, it may read the same default value on the next read so the race you are looking for requires an update right in between these two adjacent reads.
The problem is that every optimizer will coerce the two reads in your code into one, once it starts processing your code, so after that you will never get an AssertionError even if that single read evaluates to the default value.
Further, since the access to Publish.holder is unsynchronized, the optimizer is allowed to read its value exactly once and assume unchanged during all subsequent iterations. So an optimized second thread would always process the same object which will never turn back to the uninitialized state. Even worse, an optimistic optimizer may go as far as to assume that n is always 42 as you never initialize it to something else in this runtime and it will not consider the case that you want a race condition. So both loops may get optimized to no-ops.
In other words: if your code doesn’t fail on the first access, the likeliness of spotting the error in subsequent iterations dramatically drops down, possibly to zero. This is the opposite of your idea to let the code run inside a long loop hoping that you will eventually encounter the error.
The best chances for getting a data race are on the first, non-optimized, interpreted execution of your code. But keep in mind, the chance for that specific data race are still extremely low, even when running the entire test code in pure interpreted mode.
I'm trying to understand semaphores. If I want to print out something like #//}}} repeatedly (with \n after each character), how could I do that with semaphores printing only 1 visible character at a time? I have an idea on how to print out one character each using similar code for each semaphore:
public static class PrintB implements Runnable // similar class for each semaphore
{
public void run(){
for (int i=0; i<count; i++) { // printing lots to see functionality
try {
printableB.acquire(); // the semaphore
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.printf( "%s\n", "/"); // Need 2 /'s
printableC.release(); // handled B's print, move to C
}
}
}
The problem here is that the rest of my code will only print "#/}" and not "#//}}}". I don't want to just put in other print statements to accomplish this. I want to only use semaphore-related statements like .acquire() and .release() (I'm trying to learn about them after all!). Any ideas? Thank you!