Lolingckc
Lolingckc

Reputation: 21

Variable not accessible after thread start() method

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

https://en.wikipedia.org/wiki/Hello_world_program "

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

Answers (5)

Rajat Kukrety
Rajat Kukrety

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

Irwan Hendra
Irwan Hendra

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

Amal lal T L
Amal lal T L

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

Scary Wombat
Scary Wombat

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

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

Related Questions