Reputation: 21
So this is my code for the class that implements Runnable.
public class SeedDownload implements Runnable {
private StringBuilder htmlSB;
private String bingSeed;
public SeedDownload(StringBuilder string) {
htmlSB = string;
}
public void run() {
Pattern pattern = Pattern.compile("class=\"b_algo\"><h2><a href=\"(.+?)\" h=\"");
Matcher matcher = pattern.matcher(htmlSB);
if (matcher.find()) {
bingSeed = matcher.group(1);
System.out.println(bingSeed);
}
} //End of run
public String getUrlLink() {
return bingSeed;
}
}
And this is the code in my main class.
StringBuilder htmlResult = PageRead.readPage(String.format("https://bing.com/search?q=%s", query));
System.out.println(htmlResult);
SeedDownload sdBing = new SeedDownload(htmlResult);
Thread bingThread = new Thread(sdBing);
bingThread.start();
System.out.println(sdBing.getUrlLink());
And this is the output when ran.
" null
Apparently, the print in the run method could access the the variable, whereas in the main class, it couldn't. Is it something to do with the run() method being stopped and the contents of it not being accessible?
Upvotes: 1
Views: 85
Reputation: 1
In your code there are two possiblities of getting null value i.e
1) matcher.find() gives false result in that case you will get a non initialized value i.e null.
2) your print statement is executing before your thread is assigning value to bingSeed
you can check this by providing true value to if block of matcher.find() in this case you will get null value if matcher doesnt have any match.
Also, for 2nd point you can sleep your thread to wait and let the bingSeed initialize.
`bingThread.start();
Thread.sleep(millis); // it will halt your main thread and you will get your variable value.
System.out.println(sdBing.getUrlLink());`
i tried it and it worked fine after these checks
Upvotes: 0
Reputation: 148
It's not that it is not accessible, but because the modification of the variable bingSeed happens in another thread than the main thread, the System.out.println() of the main thread executes WHEN the bingSeed is still null
you have options here, either wait for the thread to finish using synchronisation or submit the thread to an Executors Service and poll the result
Upvotes: 1
Reputation: 430
The thread is producing its result independently, performing asynchronous or background processing.So the thread will produce the result independently, but the java program may have gone far already, after its request to this thread.So no result is got to the java program,but the result is given by thread correctly.This is why it is null. Use volatile
keyword for this.
Upvotes: 0
Reputation: 44854
You have two main problems
When you are running
bingThread.start();
System.out.println(sdBing.getUrlLink());
you are assuming that the Thread
has started and has already assigned a value to bingSeed
- this maybe not the case, so before calling getUrlLink
ensure that the Thread
has finished by adding
bingThread.join();
Secondly, to ensure that the most-up-to-date value of bingSeed
is being used make it volatile as in
private volatile String bingSeed;
Upvotes: 1
Reputation: 48288
You just have a volatilness issue, the getter is not retrieving the updated value of the string, so your string object must be volatile! so you can be sure that you get the updated value when you call the getter
change this
private String bingSeed;
with
private volatile String bingSeed;
from oracle doc:
Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.
Upvotes: 1