I have a question about synchronized blocks and multithreading. I have an "alternate" situation in which two synchronized blocks should be executed before and after a non-synchronized block, and such blocks should not interfere each other.
Here is (a portion of) the code:
boolean calculate = false;
synchronized(this){
Double oldSim = struct.get(pair);
if(oldSim == null || oldSim < maxThreshold)
calculate = true;
}
if(calculate)
{
// This part should be parallel
Double newSim = calculateSimilarity(...);
synchronized(this){
if(newSim > minThreshold && (oldSim == null || newSim > oldSim))
struct.put(pair, newSim);
}
}
The problem is that, in this way, different threads could execute the first sync block, while another thread could execute the second sync block. So, I though this solution:
int maxThreshold = 1.0;
if(checkAndwriteSimilarity(pair, null, false))
{
Double newSim = calculateSimilarity(table, pKey1, pKey2, pKey1Val, pKey2Val, c);
checkAndwriteSimilarity(pair, newSim, true);
}
private synchronized boolean checkAndwriteSimilarity(Pair pair, Double newSim, boolean write)
{
Double oldSim = struct.get(pair);
if(!write)
{
if(oldSim == null || oldSim < maxThreshold)
return true;
else
return false;
}
else
{
if(newSim > minThreshold && (oldSim == null || newSim > oldSim))
struct.put(pair, newSim);
return true;
}
}
Do you think it is the most correct solution? I sincerely do not like such method a lot ...
Do you have alternative solutions to suggest?
Thank you
Related
I'm working on an assignment for my computer science course requiring me to implement a Comparable interface.
We haven't discussed the interface at any sort of length except just being told it compares two objects and returns less than, greater than and equal to, but literally that's about it, which is frustrating.
I intend to do more research on it, but for now I am finding I'm confused as to why my implementation of the compareTo() method isn't working.
Eclipse is giving me an error that compareTo() must return an int, but if you notice, I am returning an integer value. So what might be the issue?
public int compareTo(Task taskToCompare) {
if(this.complete && taskToCompare.isComplete()) {
if(this.priority == taskToCompare.getPriority()) {
return 0;
}
else if(this.priority < taskToCompare.getPriority()){
return -1;
}
else if(this.priority > taskToCompare.getPriority()) {
return 1;
}
} else if(this.complete == true && taskToCompare.isComplete() == false) {
return -1;
} else if(this.complete == false && taskToCompare.isComplete() == true) {
return 1;
}
}
If the return type is int, you will have to return an int or throw an exception. Just exiting the method without a return will lead to a compiler error.
If you have a if-else-if condition, there may be a case where none of the blocks is called. You therefore should create an else statement with a return.
Also, the result of isComplete() and taskToCompare.getPriority() may change if you call the method multiple times. The compiler doesn't know if your logic prevents that.
For example, this is the case if complete is false and isComplete() also returns false. As before, the compiler doesn't know if your logic prevents that.
I think you want something like:
public int compareTo(Task taskToCompare) {
if(this.complete && taskToCompare.isComplete()) {
if(this.priority == taskToCompare.getPriority()) {
return 0;
}
else if(this.priority < taskToCompare.getPriority()){
return -1;
}
else{
return 1;
}
} else if(this.complete == true && taskToCompare.isComplete() == false) {
return -1;
} else if(this.complete == false && taskToCompare.isComplete() == true) {
return 1;
}else{
return 0;
}
}
What if this.complete == false and taskToCompare.isComplete() == false?
The compiler is complaining because you haven't covered every case.
more compact version:
public int compareTo(Task taskToCompare) {
int completeCompare = (this.complete == taskToCompare.complete) ? 0 : (this.complete ? 1 : -1);
if(completeCompare==0) {
return this.priority-taskToCompare.getPriority();
}
return completeCompare;
}
public boolean Winner() {
for (int z = 0; z < 3; z++) {
if (board[z] != null && board[z] == board[z+3] && board[z] == board[z+6]
) {
return true;
}
}
for(int i=0; i<7;i+=3){
if (board[i] != null && board[i] == board[i+1] && board[i] == board[i+2]) {
return true;}
}
}
It returns me this error: this method must return a result of type boolean. What am I doing wrong?
Right now, the function isn't guaranteed to return a boolean, because it's possible that neither of the if statements will ever be entered.
You could fix it like this (but only do this if it's actually what your logic needs!):
public boolean Winner() {
for (int z = 0; z < 3; z++) {
if (board[z] != null && board[z] == board[z+3] && board[z] == board[z+6]
) {
return true;
}
}
for(int i=0; i<7;i+=3){
if (board[i] != null && board[i] == board[i+1] && board[i] == board[i+2]) {
return true;}
}
return false;
}
The Java compiler doesn't make assumptions that a for loop will have an iteration or that an if statement block will run.
There are execution paths where there is no return statement. What happens if the execution path doesn't execute any of the existing return statements and drops to the bottom? There isn't a return there.
Add a return at the bottom.
All possible ways that the method can exit need to return something. If your code makes it through both for loops without having an if condition evaluate to true, then you need a return at the end that specifies what gets returned.
The compiler is not aware that at least one of the loops will be executed. It takes into account all the possibilities of the execution and one of them is that neither of the loops will be executed and in that case there is no return statement. So insert a return statement out of the loops as well.
The answer to this question is easy. It happened to me too. The problem in your code is that you don't say to the computer what to do in case that the "if" statement is wrong, so you just have to add an "else {return false}" to every "if". Another tip is: please make your code cleaner and readable.
public boolean Winner() {
for (int z = 0; z < 3; z++) {
if (board[z] != null && board[z] == board[z+3] && board[z] == board[z+6]) {
return true;
} else {
return false;
}
}
for (int i=0; i<7; i+=3) {
if (board[i] != null && board[i] == board[i+1] && board[i] == board[i+2]) {
return true;
} else {
return false;
}
}
}
This is the question I saw on CodingBat:
Given 2 positive int values, return the larger value that is in the range 10..20 inclusive, or return 0 if neither is in that range.
And this is the code I have written:
public int max1020(int a, int b) {
if ( a>=10 && a<=20 && b>=10 && b<=20 && a>b)
return a;
if (a>=10 && a<=20 && b>=10 && b<=20 && b>a)
return b;
if (a>=10 && a<=20 && b<=10 || b>=20)
return a;
if (a<=10 || a>=20 && b>=10 && b<=20)
return b;
else return 0;
}
I am fairly confident that it is correct but still then I click run, the websites says that: max1020(9, 21) → 0 BUT my code returns 9. Can someone help me to check through my codes what is wrong with it? :)
public int max1020(int a, int b) {
if ( a>=10 && a<=20 && b>=10 && b<=20 && a>b)
return a;
if (a>=10 && a<=20 && b>=10 && b<=20 && b>a)
return b;
if ((a>=10 && a<=20) && (b<=10 || b>=20))
return a;
if ((a<=10 || a>=20) && (b>=10 && b<=20))
return b;
else return 0;
}
Adding brackets in 3rd and 4th line will fix the problem.
I suggest you change the if statements and use else if. It is just good coding practice to use else if statements instead of several if when possible.
Your code is breaking in the third if condition, where you have || b>=20. 3rd and 4th conditions should be more specific like below:
if (a>=10 && a<=20 && (b<=10 || b>=20))
return a;
if ((a<=10 || a>=20) && b>=10 && b<=20)
return b;
Adding these parentheses will do the trick.
i would prefer to assign the checks to a variable to have a more "readable" code. but this depends on personal preferences.
public int max1020(int a, int b) {
final boolean aInRange = a>=10 && a<=20;
final boolean bInRange = b>=10 && b<=20;
if (aInRange && bInRange) {
if (a > b) {
return a;
} else if (a < b) {
return b;
} else {
return 0;
}
} else if (aInRange) {
return a;
} else if (bInRange) {
return b;
} else {
return 0;
}
}
Of course Varun's answer is correct. Additionally, I'd like to elaborate on some comments, and show an alternative approach to the problem that's much simpler and less likely to contain mistakes.
While reading the problem statement, you may notice that the method is to return a value if some conditions are met, or return 0 otherwise. So you could initialize a result with the default value of 0, change the result if the conditions are met, then return the result. That would reduce the code to:
public int max1020(int a, int b) {
int result = 0;
if (a >= 10 && a <= 20) result = a;
if (b >= 10 && b <= 20 && b > result) result = b;
return result;
}
Can't make it much simpler, I'd think. (But if you can, please comment, I love KISS! :) )
This solution produces a slightly different result, if both a and b are in range and a=b, it will return a. The problem statement is not really clear if this should happen, as also shown by the comments to Varun's answer. Coincidentally (or not) Codingbat doesn't check that condition. The proposed solution on the site also returns a in this case.
If you think it should return 0 when a=b, it's quite easy to adjust,
public int max1020(int a, int b) {
int result = 0;
if (a != b) {
if (a >= 10 && a <= 20) result = a;
if (b >= 10 && b <= 20 && b > result) result = b;
}
return result;
}
Still pretty simple :)
To explain TJCrowder's comment about indentation: If you put the body of the if statement on the next line, you should use curly braces and indent the line. Otherwise, it's far too easy to misread it, or make a mistake when you change the code.
// this can be error prone and harder to read,
// especially if you have multiple if statements,
// or add a statement to the body of the if statement in the future
// (shouldn't do this)
if (condition)
statement;
// Personally I think this is totally fine for a simple statement.
// But I know not everybody will agree
if (condition) statement;
// Usually, you'll see this formatting.
// Even without reading anything, the formatting makes it instantly clear
// which statements belong to the body of the if
if (condition) {
statement;
}
Side note: the else statement in your code belongs only to the last if. Your formatting could make that clear by not putting an empty line between those, e.g.
if (condition) statement;
else statement;
if (condition) {
statement;
} else {
statement;
}
In your code the else statement is actually obsolete, you could simply return 0; on the last line.
Varun's suggestion that you could use else ifs is correct. Theoretically, if the condition of the first if statement is true, using else if would make the code skip the tests for the other ifs and be a little more efficient. Additionally, it'd show that subsequent if statements are only reached if the previous if statements were false.
Practically however, in your code it doesn't really matter, because the method will finish and return a value if the condition is true, and subsequent if statements will never be reached anyway.
In my method under the if statement:
if (currentLocationX == 0 && currentLocationY == 4)
I have a break statement that should make the program exit out of the while loop and return true for 'answer' and for the method. Yet after some testing it seems that after returning true for 'answer', it goes back into the while loop giving the wrong results int the end. Why is my break statement not doing what it's supposed to? Thank you!
P.S. (this method calls on some other method that were not relevant to mention here)
public boolean solveMaze()
{
boolean answer = false;
int currentLocationX;
int currentLocationY;
//push starting location
pushX(2);
pushY(1);
while((isEmptyX() == false) && (isEmptyY() == false))
{
printMaze();
System.out.println();
currentLocationX = popX();
currentLocationY = popY();
//mark current location as visited
visited(currentLocationX, currentLocationY, maze);
System.out.println("Current Location: " + currentLocationX + ", " + currentLocationY);
if (currentLocationX == 0 && currentLocationY == 4)
{
answer = true;
break;
}
else
{
//push all unvisited OPEN neighbor locations into stack
if (checkEast(currentLocationX, currentLocationY) == 0)
{
pushX(eastX(currentLocationX));
pushY(eastY(currentLocationY));
}
else;
if (checkSouth(currentLocationX, currentLocationY)== 0)
{
pushX(southX(currentLocationX));
pushY(southY(currentLocationY));
}
else;
if (checkWest(currentLocationX, currentLocationY)== 0)
{
pushX(westX(currentLocationX));
pushY(westY(currentLocationY));
}
else;
if (checkNorth(currentLocationX, currentLocationY)== 0)
{
pushX (northX(currentLocationX));
pushY(northY(currentLocationY));
}
else;
}
}
return answer;
}
I wrote out the basic logic of your method as
public static boolean solveMaze() {
boolean answer = false;
int currentLocationX = 0;
int currentLocationY = 4;
while (true) {
if (currentLocationX == 0 && currentLocationY == 4) {
System.out.println("Hit the break");
break;
} else {
System.out.println("Missed the break");
}
}
return answer;
}
and if you execute it you get Hit the break. So your solveMaze() method is fine in terms of breaking out of the loop once it satisfies your if-statement. I would say that if you see your code subsequently going back into the while loop, it must be that solveMaze() was called a second time.
I recently had to code up an interpreter for Bitcoin's script language; part of this involved coming up with an algorithm to check that the control flow in a given script made sense (i.e. every OP_IF had a matching OP_ENDIF, every OP_ELSE and OP_ENDIF had a matching OP_IF, etc.).
This is what I came up with:
public class if_else_checker {
public static boolean search(String[] commands, String[] tracker, int if_index) {
boolean seenElse = false;
for (int i = if_index; i < commands.length; i++) {
if (commands[i].equals("OP_ELSE")) {
if (seenElse == true && tracker[i] == null) return false;
if (tracker[i] == null) {
tracker[i] = "OP_ELSE";
seenElse = true;
}
}
else if (commands[i].equals("OP_ENDIF")) {
if (tracker[i] != null && tracker[i].equals("OP_ENDIF"))
{
continue;
}
tracker[i] = "OP_ENDIF";
return true;
}
else if (commands[i].equals("OP_IF")) {
if (tracker[i] != null && tracker[i].equals("OP_IF")) {
continue;
}
tracker[i] = "OP_IF";
if (search(commands, tracker, i + 1) == false) return false;
}
}
return false;
}
public static boolean validate(String[] args)
{
String[] tracker = new String[args.length];
for (int i = 0; i < args.length; i++)
{
if (args[i].equals("OP_IF"))
{
if (tracker[i] == null || !tracker[i].equals("OP_IF"))
{
tracker[i] = "OP_IF";
if (search(args, tracker, i + 1) == false) return false;
}
else continue;
}
else if (args[i].equals("OP_ELSE"))
{
if (tracker[i] == null || !tracker[i].equals("OP_ELSE")) return false;
}
else if (args[i].equals("OP_ENDIF"))
{
if (tracker[i] == null || !tracker[i].equals("OP_ENDIF")) return false;
}
}
return true;
}
public static void main(String[] args)
{
System.out.println(validate(args));
}
}
It works, but I was wondering if there is a way to optimise it/if there is a standard way of doing this? (One optimisation is to have validate() return the index of the OP_ENDIF it finds, rather than a boolean; this would change runtime from quadratic-time to linear).
The best way of solving this is by using a Stack data structure. Every new opening instruction (e.g. OP_IF) is pushed into the stack. When you find a closing instruction (e.g. OP_ENDIF), you pop the top element of the stack and check if it is the corresponding opening instruction for that closing instruction. If so, then it's valid, and you proceed to the next step. In the end, if the stack is empty then the control flow you're checking is correct. Otherwise, it's not.