0

My last question to this topic and the corresponding answer did not explain all details. So I decide to simplify the code:

List<String> wis = new ArrayList<String>();
for(int i=0;i<3000;i++) {
    wis.add("test_" + i);
}   
DayCalc calc = new DayCalc();   
List<List<String>> partition = MyPartition.partition(wis, 30);
ExecutorService executor = Executors.newFixedThreadPool(4);
for(List<String> part: partition) {
    Runnable worker = new DayCalcWorker(part, calc);
    executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
    // Execute all Threads
}

The shared class object "calc" is used by all executed threads:

public class DayCalc {
    private static int CURRENT_DAY_OF_YEAR = DateTimes.getCurrentCalendarDay();
    ArrayList<String> kwContentArray;

    public DayCalc() {
       kwContentArray = new ArrayList<String>();
    }

    private int getCurrentCalendarDay(Calendar cal) {
       // Reset time to start of day (00:00)
       cal.set(Calendar.HOUR, 0);
       cal.set(Calendar.MINUTE, 0);
       // Get starting day
       Calendar currentTime2 = StartDate.getStartDate();
       System.out.println("Day: " + CURRENT_DAY_OF_YEAR);
       System.out.println("Start Date: " + currentTime2.getTime());
       int day = (int) Convert.daysBetween(currentTime2.getTime(), cal.getTime());
       return day;
    }

    public void setValueFromWorkItem(String wiID, String duration, Calendar cal) {
       if (duration != null) {
        this.setDurationValues(wiID, duration, cal);
       } else {
        int currentDay = getCurrentCalendarDay(cal);
        long time = 0;
        kwContentArray.add(String.valueOf(time));
       }
    }

  // [...]
}

Thread Worker class:

public class DayCalcWorker implements Runnable {

    private List<String> wis;
    private DayCalc dayCalc;    
    GregorianCalendar cal = new GregorianCalendar();
    GregorianCalendar cal2 = new GregorianCalendar();    

    public DayCalcWorker(List<String> wis, DayCalc dayCalc) {
      this.wis = wis;
      this.dayCalc = dayCalc;
    }    

    @Override
    public void run() {
       if (wis != null && wis.size() > 0) {
           for(String wi: wis) {
             long randomDate = System.currentTimeMillis() + Random.getValue();
             cal.setTime(new Date(randomDate));
             dayCalc.setValueFromWorkItem(wi, "24", cal);
           }
       }
    }
}

Question

Is it save not to synchronize the methods setValueFromWorkItem or getCurrentCalendarDay because they use e.g. only a local created calendar object from each Worker thread?

Because the object calc from the class DayCalc is shared I have only to keep care of objects which are created within this class and not with passed objects from Worker Threads which are calling methods of calc, haven't I?

Note that the code itself makes no sence at all. It just should explain that I use mutable calendar objects which need to synchronized (maybe).

4

1 回答 1

1

No, it's not safe. You're modifying a shared list (kwContentArray) from inside the setValueFromWorkItem() method. So this modification, and all the other accesses to this shared list (read or write), must be synchronized. You coud also use a concurrent List implementation, if that suits your needs.

于 2013-04-24T09:45:46.260 回答