在线程java中访问变量

时间:2016-05-20 07:15:55

标签: java multithreading

我的线程类中有一个全局变量,它是<div class="hover-to-show-link"> <a href="#"> <h2>Logo</h2> <p class="hover-to-show">text</p> </a> </div> <div class="hover-to-show-link"> <a href="#"> <h2>Profilering</h2> <p class="hover-to-show">text</p> </a> </div> <div class="hover-to-show-link"> <a href="#"> <h2 >Profilering</h2> <p class="hover-to-show">text</p> </a> </div> <div class="hover-to-show-link"> <a href="#"> <h2>Profilering</h2> <p class="hover-to-show">text</p> </a> </div>。我定期从ArrayList<>方法运行此线程;每当这个线程运行时,我就用main()方法填充这个列表。我想从run()方法访问此列表,但每当我从main()访问此列表时,我都会得到一个空列表。请建议我如何实现这一点,以下是我的代码示例。

main()

这是我的线程类,

private static ArrayList<SampleClass> allproxyDetailsPojoList = null;   

public static void main(String[] args) {
    try {
        ScheduledExecutorService threadSchedulerService = Executors.newScheduledThreadPool(1);
        threadSchedulerService.scheduleAtFixedRate(new SampleThreadClass(), 0, 5, TimeUnit.MINUTES);

        Thread.sleep(8000);

        SampleThreadClass sampleThreadClass = new SampleThreadClass();

        // here i am getting list empty
        allproxyDetailsPojoList = sampleThreadClass.getSampleClassList();

    } catch (Exception e) {

    }
}

注意:无法使用public class SampleThreadClass implements Runnable { ArrayList<SampleClass> sampleClassList = null; @Override public void run() { MyDao myDao = null; try { myDao = new MyDao(); sampleClassList = myDao.getSampleClassList(); } catch (Exception e) { } } public ArrayList<SampleClass> getSampleClassList(){ return sampleClassList; } } 关键字。

5 个答案:

答案 0 :(得分:3)

您需要了解类的哪些实例与类定义形成对比。在您的代码中,您将创建该类的两个实例。由于变量不是静态的,因此每个实例都有自己的变量实例。您无法通过实例2的引用访问实例1的变量。

try {
    ScheduledExecutorService threadSchedulerService = Executors.newScheduledThreadPool(1);
    threadSchedulerService.scheduleAtFixedRate(new SampleThreadClass(), 0, 5, TimeUnit.MINUTES);
                                           //  ^ 1st Instance
    Thread.sleep(8000);

    SampleThreadClass sampleThreadClass = new SampleThreadClass(); // <-- 2nd Instance

因此,要使用单个实例,请将其更改为

try {
    ScheduledExecutorService threadSchedulerService = Executors.newScheduledThreadPool(1);

    SampleThreadClass sampleThreadClass = new SampleThreadClass();
    threadSchedulerService.scheduleAtFixedRate(sampleThreadClass , 0, 5, TimeUnit.MINUTES);

    Thread.sleep(8000);

为了避免&#34;奇怪的行为&#34;,我还要同步对sampleClassList的访问权限。

另外,为了避免NPE,我要改变

public ArrayList<SampleClass> getSampleClassList(){
    return sampleClassList;
}

public ArrayList<SampleClass> getSampleClassList(){
    if ( null != sampleClassList )
        return sampleClassList;
    return Collections.emptyList();
}

但请注意,这个空列表是不可变的。如果您需要一个可变列表,则可以返回new ArrayList<SampleClass>()

P.S。

使用睡眠并不能确保此代码稳定。如果您希望在等待服务调用至少执行一次后实际存在列表,则应该这样做而不是等待固定的时间段。但这将是另一个问题。

答案 1 :(得分:2)

您正在阅读

中创建的对象列表
SampleThreadClass sampleThreadClass = new SampleThreadClass();

而不是你在这里创建并执行的那个:

 threadSchedulerService.scheduleAtFixedRate(new SampleThreadClass(), 0, 5, TimeUnit.MINUTES);

ArrayList<SampleClass> sampleClassList = null; 

是一个实例变量,而不是全局变量。

我认为你得到一个空值而不是一个空列表。

答案 2 :(得分:1)

创建线程类的对象后,需要启动线程。可以使用start()函数启动线程。 当join()函数与start()一起使用时,您的主程序将等待您的线程执行。线程完成执行后,主程序将开始运行。 如果您不使用join(),则主程序将打印空{,{1}},因为该线程未完成执行。

答案 3 :(得分:1)

因为您正在使用执行程序服务,所以不需要调用start()。所以你就到了这里。但是,您正在创建两个不同的SampleThreadClass。第一个是在这里创建的:

ScheduledExecutorService threadSchedulerService = Executors.newScheduledThreadPool(1);
        threadSchedulerService.scheduleAtFixedRate(new SampleThreadClass(), 0, 5, TimeUnit.MINUTES);

第二个是在这里创建的,执行者服务不知道这个,因为它从未传递给它。

SampleThreadClass sampleThreadClass = new SampleThreadClass();

这是如何修复:

SampleThreadClass sampleThreadClass = new SampleThreadClass();
 ScheduledExecutorService threadSchedulerService = Executors.newScheduledThreadPool(1);
        threadSchedulerService.scheduleAtFixedRate(sampleThreadClass, 0, 5, TimeUnit.MINUTES);

        Thread.sleep(8000);

        // here i am getting list empty
        allproxyDetailsPojoList = sampleThreadClass.getSampleClassList();

在这个修复之后,接下来的事情是静态变量在线程中及时可见,它应该被定义为volatile。

答案 4 :(得分:1)

在@ apadana回答之上添加更多信息(保留相同的类实例,已提交给ExecutorService

将任务提交到ExecutorService后,您的任务和主线程并行运行。在您的任务完成之前,主线程不会获得该值。由于您在完成任务时访问变量,因此您将获得空值。

不要使用sleep来填充值。取决于ExecutorService invokeAll API或使用CountDownLatch

看看工作代码示例:

How to wait for a thread that spawns it's own thread?