Java 带参数的forloop中的多线程

Java 带参数的forloop中的多线程,java,multithreading,Java,Multithreading,我相信我得到的数据是错误的,因为实例变量不是线程安全的 我试图使用多线程的方式,根据列表一次打开(最多)13个线程。我在服务中使用它,需要将参数传递到run方法中,所以我制作了一些实例变量并设置它们。我还希望在进入第一个for循环的下一个迭代之前执行这十三个方法 private EnergyPortalGroup superGroup; private EnergyPortalSubGroups singleSubGroup; private BillingPeriod singlePeriod

我相信我得到的数据是错误的,因为实例变量不是线程安全的

我试图使用多线程的方式,根据列表一次打开(最多)13个线程。我在服务中使用它,需要将参数传递到run方法中,所以我制作了一些实例变量并设置它们。我还希望在进入第一个for循环的下一个迭代之前执行这十三个方法

private EnergyPortalGroup superGroup;
private EnergyPortalSubGroups singleSubGroup;
private BillingPeriod singlePeriod;
private DateTime[] dateTimeArray;

private void parseGroup(EnergyPortalGroup superGroup) throws InterruptedException{
    EnergyPortalSubGroupsCriteria criteria = new EnergyPortalSubGroupsCriteria();
    criteria.setGroupId(superGroup.getId());
    List<EnergyPortalSubGroups> wholeSubGroupList = subgroupsFactory.readList(criteria);
    for (EnergyPortalSubGroups singleSubGroup : wholeSubGroupList){
        this.singleSubGroup = singleSubGroup;
        this.deleteSubGroupRecordsFromDB(singleSubGroup);
        List<BillingPeriod> billingPeriodList = this.getPreviousTwelveBillingPeriods(singleSubGroup, superGroup);   
        if (billingPeriodList != null && billingPeriodList.size() > 0){
            Thread[] threads = new Thread[billingPeriodList.size()];
            for (int i = 0; i < billingPeriodList.size(); i++){
                this.singlePeriod = billingPeriodList.get(i);
                threads[i] = new Thread(this);
                threads[i].start();
            }               
            for (Thread thread : threads){
                thread.join();
            }
        }
    }
}
私人能源门户集团超群;
私人能源门户子组单子组;
私人计费周期单周期;
私有日期时间[]日期时间数组;
private void parseGroup(EnergyPortalGroup超组)引发InterruptedException{
EnergyPortalSubGroupsCriteria条件=新的EnergyPortalSubGroupsCriteria();
criteria.setGroupId(superGroup.getId());
List-whistubgrouplist=子工厂.readList(标准);
对于(EnergyPortalSubGroups SingleSubgroups:批发分组列表){
this.singleSubGroup=singleSubGroup;
此.deleteSubleRecordsFromDB(singleSubGroup);
List billingPeriodList=this.GetPreviousTwevereBillingPeriods(singleSubGroup,superGroup);
if(billingPeriodList!=null&&billingPeriodList.size()>0){
线程[]线程=新线程[billingPeriodList.size()];
对于(int i=0;i
以下是我的重写运行方法:

@Override
public void run(){
    List<GroupSummarization> groupSummarizationsToWriteList = new ArrayList<>();    
    WidgetDataSummationHolder holder = new WidgetDataSummationHolder();
    holder = energyPortalService.getEnergyPortalWidgetsSummedData(singleSubGroup, null, null, singlePeriod);    
    parseSummationHolder(groupSummarizationsToWriteList, holder, singleSubGroup, dateTimeArray, singlePeriod);
    processBatchLists(groupSummarizationsToWriteList, superGroup, singlePeriod);
}
@覆盖
公开募捐{
List GroupSummationStowriteList=新建ArrayList();
WidgetDataSummationHolder=新的WidgetDataSummationHolder();
holder=energyPortalService.GetEnergyPortalWidgetSSUMEDDATA(singleSubGroup,null,null,singlePeriod);
parseSummationHolder(GroupSummationStowriteList,holder,singleSubGroup,dateTimeArray,singlePeriod);
ProcessBatchList(GroupSummationStowriteList、superGroup、singlePeriod);
}

有人能帮我把这根线弄安全吗?我显然是多线程新手,我尝试用构造函数传递这些变量,但我有一些自动连接的服务是空的,我在这一行得到一个空指针
holder=energyPortalService.getEnergyPortalWidgetsSummedData(singleSubGroup,null,null,singlePeriod)

根据您提供的代码,energyPortalService有时不能为空,其他时间不能为空。如果在启动新线程时它不为null(this),那么如果要使用新线程(()->{…}),它应该在那里


(既然你说的是自动布线,我就认为osgi和aop以及诸如此类的邪恶行为可能会发生很多恶作剧。)

根据你提供的代码,energyPortalService有时不能为空,其他时候不能为空。如果在启动新线程时它不为null(this),那么如果要使用新线程(()->{…}),它应该在那里


(既然你说的是自动布线,我就认为osgi和aop以及诸如此类的邪恶行为可能会发生很多恶作剧。)

最后,我选择了ExecutorService和一些建议的新类/服务。下面是一个例子,以防其他人遇到此类问题:

for (final Object x : list){
    List<Object> someList = getList();
    if (!Collections.isEmpty(someList)){
        ExecutorService executorService = Executors.newCachedThreadPool();
        List<Future<?>> futures = new ArrayList<Future<?>>();
        for (final Object n : someList){
            futures.add(executorService.submit(new Runnable(){
                @Override
                public void run(){
                    someOtherService.process(parameters)
                }
            }));
        }

        for (Future<?> f : futures){
             try {
                 f.get();
             } catch (InterruptedException | ExecutionException e) {
                 //do some logging
             }
        }
    }
}
for(最终对象x:列表){
List someList=getList();
如果(!Collections.isEmpty(someList)){
ExecutorService ExecutorService=Executors.newCachedThreadPool();
列表>();
for(最终对象n:someList){
futures.add(executorService.submit(newrunnable()){
@凌驾
公开募捐{
someOtherService.process(参数)
}
}));
}
for(未来f:未来){
试一试{
f、 get();
}捕获(中断异常|执行异常e){
//做些日志记录
}
}
}
}
基本上,这是调用管理线程池的ExecutorService。我调用newCachedThreadPool,以便它根据需要创建新线程,而不是假设如果您看到
newFixedThreadPool(n)
,我知道在这种情况下需要多少线程。但是,为了确保线程大小的一致性,在我循环内部循环之后,我循环未来列表(未来是异步计算的未来结果),并调用f.get,如果需要,它将等待计算完成,然后检索其结果

这对我所需要的非常有效。关键部分是,在重写的run函数中,process方法接受您想要的任何参数(注意使用
final
),而不是在调用构造函数时试图强制feed run()或担心自动连线服务。这绕过了所有这些


感谢所有让我走上正确道路的人

最后,我选择了ExecutorService和一些建议的新类/服务。下面是一个例子,以防其他人遇到此类问题:

for (final Object x : list){
    List<Object> someList = getList();
    if (!Collections.isEmpty(someList)){
        ExecutorService executorService = Executors.newCachedThreadPool();
        List<Future<?>> futures = new ArrayList<Future<?>>();
        for (final Object n : someList){
            futures.add(executorService.submit(new Runnable(){
                @Override
                public void run(){
                    someOtherService.process(parameters)
                }
            }));
        }

        for (Future<?> f : futures){
             try {
                 f.get();
             } catch (InterruptedException | ExecutionException e) {
                 //do some logging
             }
        }
    }
}
for(最终对象x:列表){
List someList=getList();
如果(!Collections.isEmpty(someList)){
ExecutorService ExecutorService=Executors.newCachedThreadPool();
列表>();
for(最终对象n:someList){
futures.add(executorService.submit(newrunnable()){
@凌驾
公开募捐{
someOtherService.process(参数)
}
}));
}
for(未来f:未来){
试一试{
f、 get();
}捕获(中断异常|执行异常e){
//做些日志记录
}
}
}
}
基本上这是电话