0

以下代码从一个大列表中创建任务,该列表分为子列表(列表 l):

        ExecutorService executor = Executors.newFixedThreadPool(cpu);
        KwArrayDuration duration = new KwArrayDuration();
        for (List<Item> l : partition) {
            Runnable readingTask = new MainReadingTask(l, duration);
            executor.execute(readingTask);
        }
        executor.shutdown();
        while (!executor.isTerminated()) {
            // Execute all Threads
        }

工作线程的示例代码:

public class MainReadingTask implements Runnable {

private KwArrayDuration duration;
private List<Item> wis;

    public MainReadingTask(List<Item> wis, KwArrayDuration duration) {
       this.wis = wis;
       this.duration = duration;
    }

    @Override
    public void run() {
    try {
      for (Item wi : wis) {
        duration.setValueFromItem(wi.getId(), null, cal);
      }
    } catch (IOException e) {
        e.printStackTrace();
    }   
    }

}

该类的对象KwArrayDuration被所有线程用作一个storage类,该类将每个任务的结果插入到数组列表 ( kwContentArray) 中。

此外,该类KwArrayDuration包含一些计算某些东西的方法。这些方法由每个工作线程调用:

public synchronized void setValueFromItem(String id, DurationTime duration, Calendar cal) {
   if(duration != null) {
    try {
       this.setDurationValues(id, duration, cal);
    } catch (IOException e) {
       e.printStackTrace();
    }
   } else {
    int currentDay = getCurrentCalendarDay(cal);
    long time = 0;
    for (int i = currentDay; i < kwContentArray.size(); i++) {
       KwArrayWrapper currentDayKW = kwContentArray.get(i);
       currentDayKW.setValues(wi, String.valueOf(time));
       kwContentArray.set(i, currentDayKW);
    }
   }
}

问题:

真的需要setValueFromItem从共享KwArrayDuration实例同步功能吗?我认为是的,因为如果调度程序在此行之后停止,结果可能会有所不同

int currentDay = getCurrentCalendarDay(cal);

另一个线程使用这个 int 值进行进一步的逻辑。

4

1 回答 1

0

有两个原因你需要synchronize

  1. 如果持续时间是可变的和共享的,或者如果 cal 在其他线程之间共享,那么调用getCurrentCalendarDay(cal)可能会导致与进入方法时预期的结果不同的结果。duration如果它是可变和共享的,这也适用。

  2. 如果kwContentArray是共享的,您还需要同步。

故事的寓意是同步访问所有共享的可变数据。

于 2013-04-22T10:54:17.893 回答