我的线程类中有一个全局变量,它是<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;
}
}
关键字。
答案 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>()
。
使用睡眠并不能确保此代码稳定。如果您希望在等待服务调用至少执行一次后实际存在列表,则应该这样做而不是等待固定的时间段。但这将是另一个问题。
答案 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
看看工作代码示例: