Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java线程中访问变量_Java_Multithreading - Fatal编程技术网

在java线程中访问变量

在java线程中访问变量,java,multithreading,Java,Multithreading,我的thread类中有一个全局变量,它是ArrayList。我定期从main()方法运行此线程;每当此线程运行时,我都在run()方法中填充此列表。我想从main()方法访问此列表,但无论何时从main()访问此列表,我都会得到一个空列表。请建议我如何实现这一点,下面是我的代码示例 private static ArrayList<SampleClass> allproxyDetailsPojoList = null; public static void main(Stri

我的thread类中有一个全局变量,它是
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) {

    }
}
私有静态ArrayList allproxyDetailsPojoList=null;
公共静态void main(字符串[]args){
试一试{
ScheduledExecutorService threadSchedulerService=执行者。newScheduledThreadPool(1);
threadSchedulerService.scheduleAtFixedRate(新的SampleThreadClass(),0,5,TimeUnit.MINUTES);
睡眠(8000);
SampleThreadClass SampleThreadClass=新的SampleThreadClass();
//在这里,我得到的名单是空的
allproxyDetailsPojoList=sampleThreadClass.getSampleClassList();
}捕获(例外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;
    }
}
公共类SampleThreadClass实现可运行{
ArrayList sampleClassList=null;
@凌驾
公开募捐{
MyDao MyDao=null;
试一试{
myDao=新的myDao();
sampleClassList=myDao.getSampleClassList();
}捕获(例外e){
}
}
公共ArrayList getSampleClassList(){
返回sampleClassList;
}
}

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

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

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

SampleThreadClass sampleThreadClass = new SampleThreadClass();
而不是您在此处创建并执行的:

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

ArrayList sampleClassList=null;
是实例变量,而不是全局变量


我认为您得到的是一个空值,而不是一个空列表。

您不需要调用start(),因为您使用的是executor服务。那么你就到这里来了。但是,您正在创建两个不同的SampleThreadClass。第一个是在这里创建的:

ScheduledExecutorService threadSchedulerService = Executors.newScheduledThreadPool(1);
        threadSchedulerService.scheduleAtFixedRate(new SampleThreadClass(), 0, 5, TimeUnit.MINUTES);
第二个是在这里创建的,executorservice不知道这个,因为它从未被传递给它

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

您需要了解与类定义相比,类的实例是什么。在代码中,您创建了该类的两个实例。因为变量不是静态的,所以每个实例都有自己的变量实例。无法通过实例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
但是为了避免“奇怪的行为”,我还同步访问
sampleClassList

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

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

public ArrayList getSampleClassList(){
if(null!=sampleClassList)
返回sampleClassList;
返回集合。emptyList();
}
但请记住,这个空列表是不可变的。如果您需要一个可变列表,只需返回一个
新的ArrayList()

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

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

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

不要使用睡眠填充值。而是依赖于
invokeAll
API或使用

查看工作代码示例:


他可以永远等待,因为他从与填充的实例不同的实例获取列表。实际上,他应该使用已提交给ExecutorService的相同实例。他正在创建一个不必要的实例。他正在使用同一个类。他使用的不是同一个实例。这些术语的使用不准确是导致新手犯此类错误的原因。我指的是实例。谢谢你给我一个改变来纠正我的评论。
try {
    ScheduledExecutorService threadSchedulerService = Executors.newScheduledThreadPool(1);

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

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