繁体   English   中英

在线程java中访问变量

[英]Accessing variable in a thread java

我的线程类中有一个全局变量,它是一个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;
    }
}

注意:不能使用static关键字。

您需要了解类的哪些实例与类定义形成对比。 在您的代码中,您将创建该类的两个实例。 由于变量不是静态的,因此每个实例都有自己的变量实例。 您无法通过实例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);

为了避免“奇怪的行为”,我还要同步访问sampleClassList

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

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

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

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

PS

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

您正在阅读您在其中创建的对象的列表

SampleThreadClass sampleThreadClass = new SampleThreadClass();

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

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

这个

ArrayList<SampleClass> sampleClassList = null; 

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

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

一旦你创建了一个线程类的对象,你需要启动该线程。 可以使用start()函数start()线程。 join()函数与start()一起使用时,主程序将等待你的线程执行。 线程完成执行后,主程序将开始运行。 如果你不使用join()你的主程序将打印空的allproxyDetailsPojoList ,因为线程没有完成执行。

由于您正在使用执行程序服务,因此无需调用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。

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

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

不要使用sleep来填充值。 而是依赖于ExecutorService invokeAll API或使用CountDownLatch

看看工作代码示例:

如何等待一个产生它自己的线程的线程?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM