线程start()方法后无法访问变量

时间:2017-08-04 06:49:50

标签: java

所以这是我实现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;
    }

}

这是我主要课程中的代码。

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());

这是跑步时的输出。

&#34;空

  

https://en.wikipedia.org/wiki/Hello_world_program&#34;

显然,run方法中的print可以访问变量,而在主类中,它无法访问。是否与run()方法被停止并且其内容无法访问有关?

5 个答案:

答案 0 :(得分:1)

你只是有一个volatilness问题,getter没有检索字符串的更新值,所以你的字符串对象必须是易变的!所以你可以确定在调用getter时获得更新的值

更改此

private String bingSeed;

private volatile String bingSeed;
来自oracle doc

  

使用volatile变量可降低内存一致性的风险   错误,因为对volatile变量的任何写入都会建立一个   在与之后的相关读取之前发生   变量。这意味着始终对volatile变量进行更改   其他线程可见。更重要的是,它还意味着当a   线程读取一个volatile变量,它不仅看到最新的变化   对于挥发性,还有导致代码的副作用   变化

答案 1 :(得分:1)

并不是因为它不可访问,而是因为变量bingSeed的修改发生在另一个线程而不是主线程,所以主线程的System.out.println()执行WHEN bingSeed仍为空

你有选择,要么等待线程完成同步,要么将线程提交给执行者服务并轮询结果

答案 2 :(得分:1)

你有两个主要问题

当你跑步时

{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}

{% block field %}
     <div>
            <img src="{{ vich_uploader_asset(object, 'logoFichier') }}" alt="" style=""/>
    </div>
{% endblock %}

您假设 bingThread.start(); System.out.println(sdBing.getUrlLink()); 已经开始并且已经为Thread分配了一个值 - 这可能不是这种情况,所以在致电bingSeed之前确保getUrlLink已完成添加

Thread

其次,要确保使用bingThread.join(); 最新值,请将其设置为易失性,如

bingSeed

答案 3 :(得分:0)

线程独立地生成它的结果,执行异步或后台处理。所以线程将独立地产生结果,但java程序可能已经走了很远,在它对此线程的请求之后。所以没有结果到达java程序,但结果是由线程正确给出的。这就是为什么它是null。请使用volatile关键字。

答案 4 :(得分:0)

在您的代码中,有两种获取空值的可能性,即

1)matcher.find()给出错误的结果,在这种情况下你会得到一个非结果    初始值,即null。

2)在线程分配值之前,您的print语句正在执行    到bingSeed

你可以通过为matcher.find()块提供真值来检查这一点 在这种情况下,如果匹配器没有任何匹配,您将获得空值。

此外,对于第二点,您可以让线程等待并让bingSeed初始化。

     `bingThread.start();
     Thread.sleep(millis);  // it will halt your main thread and you will get your variable value.
     System.out.println(sdBing.getUrlLink());`

我试过了,这些检查后它运作良好