码迷,mamicode.com
首页 > 其他好文 > 详细

一次定位不准的问题

时间:2019-02-27 17:57:00      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:string   完成   解决   回调   lis   错误   线程   type   cut   

花了三天时间试图做一个永远不能完成的任务。
需求:程序逻辑出现错误

@Autowired
private TwoHoursTaskThread twoHoursTaskThread;// 该实例是实现Runnable的一个单例

for(int i=0,l=list.size();i<l;i++)
{
ForfeitVO forfeitVO = list.get(i);
twoHoursTaskThread.setForfeitVO(forfeitVO);
Executors.newScheduledThreadPool(twoHoursTaskThread,10,TimeUnit.SECONDS);
}

  理想的情况是:每次循环在一个线程中设置不同的ForfeitVO值,执行list.size()次 延时线程。
  实际情况是:线程池只启用了一个线程。

  错误原因:最开始是以为,这size个线程因为共享ForfeitVO变量,而线程池开启一个线程需要时间(还有延时开启的因素)造成线程开始执行的时候,用到的ForfeitVO变量已经不是和他在同一个循环里产生的ForfeitVO变量了。

  后续的解决思路都是围绕着如何不共享变量展开的。最简单的方式就是 每次从spring 容器取出@Scope(value= prototype)的twoHoursTaskThread非单例,这样就不会共享实例变量了。可是这样就每次从spring容器那产生bean,肯定对内存有不少的消耗。
所以就想寻求 既能用单例(twoHoursTaskThread),又能避开共享变量。能想到的就是ThreadLocal,可是,如何能保证线程还没开始就已经初始化过这个=ThreadLocal变量呢?也就是如何向这个单实例传入不同参数呢?通过set方法或者初始化传参是不行的,只能通过最后一种方法,就是回调函数,可是这个回调函数如何判断哪个线程对应哪个ForfeitVO值呢,每个线程唯一不同的就是序号了,遂想就用这个i当做回调函数的参数吧,可是在for循环里怎么往线程里传参数呢,找到Thread(Runnable runnable,String name)初始化,这个name就用循环中的i,即:new Thread(twoHoursTaskThread,i).start()开启这个线程。可是这不是一样要新建对象吗,一样的浪费内存。抱着试试看的态度一试,结果居然发现只有一个线程跑起来。恍然大悟,一个实例只能开启一个线程,所以,想通过单例模式开多线程的路一开始就是个死路。

  总结:问题定位不准惹的祸。

 

一次定位不准的问题

标签:string   完成   解决   回调   lis   错误   线程   type   cut   

原文地址:https://www.cnblogs.com/hezhiyuan/p/10445098.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!