同步工作线程使用的共享对象

时间:2013-04-24 09:34:42

标签: java multithreading calendar synchronization

我对这个主题的最后一个问题和相应的答案没有解释所有细节。所以我决定简化代码:

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
}

共享类对象“calc”由所有执行的线程使用:

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类:​​

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);
           }
       }
    }
}

问题

是保存来同步方法setValueFromWorkItemgetCurrentCalendarDay,因为它们使用例如每个工作线程只有本地创建的日历对象

因为类calc中的对象DayCalc是共享的,所以我只需要处理在这个类中创建的对象,而不是处理来自正在调用{{的方法的工作线程的传递对象。 1}},不是吗?

请注意,代码本身根本没有任何意义。它应该解释我使用需要同步的可变日历对象(可能)。

1 个答案:

答案 0 :(得分:1)

不,这不安全。您正在kwContentArray方法内修改共享列表(setValueFromWorkItem())。因此,必须同步此修改以及对此共享列表(读取或写入)的所有其他访问。如果符合您的需要,您还可以使用并发List实现。