Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/229.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
检测对同步函数java的并发访问_Java_Android_Multithreading_Arraylist_Concurrency - Fatal编程技术网

检测对同步函数java的并发访问

检测对同步函数java的并发访问,java,android,multithreading,arraylist,concurrency,Java,Android,Multithreading,Arraylist,Concurrency,我在android应用程序中有一个多线程环境。我使用单例类来存储数据。此singleton类包含一个arraylist,可使用同步方法访问该arraylist 应用程序使用此arraylist在应用程序中渲染图像 最初的问题:并发修改错误经常出现,所以我使GetArrayList函数同步化 当前问题:并发修改错误未出现,但介于返回的空arraylist之间,可能是在存在并发访问时返回的 目标:我想检测并发修改的时间,这样就可以返回arraylist的最后一个状态,而不是返回空的arraylist

我在android应用程序中有一个多线程环境。我使用单例类来存储数据。此singleton类包含一个arraylist,可使用同步方法访问该arraylist

应用程序使用此arraylist在应用程序中渲染图像

最初的问题:并发修改错误经常出现,所以我使GetArrayList函数同步化

当前问题:并发修改错误未出现,但介于返回的空arraylist之间,可能是在存在并发访问时返回的

目标:我想检测并发修改的时间,这样就可以返回arraylist的最后一个状态,而不是返回空的arraylist

public synchronized List<FrameData> getCurrentDataToShow() {
    List<FrameData> lisCurrDataToShow = new ArrayList<FrameData>();
    //for (FrameData fd : listFrameData) {//concurrent modification exception
    //todo iterator test
    Iterator<FrameData> iterator = listFrameData.iterator();
    while (iterator.hasNext()) {
        FrameData fd = iterator.next();
        long currentTimeInMillis = java.lang.System.currentTimeMillis();

        if ((currentTimeInMillis > fd.getStartDate().getTime() && currentTimeInMillis < fd.getEndDate().getTime()) || (fd.isAllDay() && DateUtils.isToday(fd.getStartDate().getTime()))) {
            if (new File(ImageFrameActivity.ROOT_FOLDER_FILES + fd.getFileName()).exists()) {
                lisCurrDataToShow.add(fd);
            }
        }
    }
    if (lisCurrDataToShow.size() == 0) { 
        lisCurrDataToShow.add(new FrameData(defaultFileName, null, null, null, String.valueOf(120), false));
    }
    return lisCurrDataToShow;
}
提及

请帮忙

编辑1:

这个问题很少发生,不是每次都会发生

如果一个线程正在访问getCurrentDataToShow,而另一个线程试图访问该函数,该函数将返回什么??我是多线程新手,请指导 编辑2

在oncreate中,定期调用以下单例方法

DataModelManager.getInstance.getCurrentDataToShow; DataModelManager.getInstance.parseDataresponseString

完全单例类


这是您问题中目前唯一可以回答的部分:

如果一个线程正在访问getCurrentDataToShow,而另一个线程试图访问该函数,该函数将返回什么

这取决于是否在同一目标对象上调用getCurrentDataToShow;i、 这是什么

如果这两个调用相同,则第一个调用将在第二个调用开始之前完成

如果这是不同的,您将锁定不同的对象,这两个调用可能重叠。两个线程需要锁定同一个对象以实现互斥

无论哪种情况,此方法都不会更改listFrameData集合。因此,调用是否重叠并不重要!然而,显然还有其他东西正在改变收藏的内容。如果该代码根本没有同步,或者正在另一个锁上同步,那么这可能是问题的根源

现在你说你现在没有看到ConcurrentModificationException。这表明,但并不能证明根本不存在同步问题。这表明但不能证明你目前的问题是一个逻辑错误


但正如我在上面所评论的,有理由怀疑您向我们展示的代码是否真实反映了您的真实代码。如果需要更明确的诊断,则需要提供MVCE。

此方法是否具有对listFrameData的独占访问权限?您需要确保没有其他方法可以同时修改它,即所有修改它的方法都需要在同一个监视器上同步。您可能希望查看类似于处理并发修改的内容,例如,如果遍历操作的数量远远超过了突变。我试着使用CopyOnWriteArrayList,它导致了这种空arraylist返回频率更高的情况,我希望您得到ConcurrentModificationException,无论您使用显式迭代器还是增强型for语句,因为后者是前者的语法糖。你确定你的列表不是空的吗?是否正在为listFrameData的某个位置指定新值?是。我肯定名单不是空的。如果lisCurrDataToShow.size==0{/..}正在运行,则当this函数未同步时,立即引发并发修改。可能由于其他线程正在访问arraylist,因此未访问arraylist。感谢您的响应。我已经编辑了我的问题并添加了完整的singleton类。我认为我无法使用singleton管理多线程环境。我是多线程方面的新手,我怀疑问题在于有时使用空字符串或由空JSON数组组成的字符串调用parseData。但这仍然不是一个MVCE。我们无法运行此代码来演示问题。
public class DataModelManager {
    private static DataModelManager dataModelManager;
    private ImageFrameActivity imageFrameAct;
    private String defaultFileName;
    public List<FrameData> listFrameData = new ArrayList<FrameData>();
//    public CopyOnWriteArrayList<FrameData> listFrameData= new CopyOnWriteArrayList<FrameData>();
    private String screensaverName;
    private boolean isToDownloadDeafultFiles;
    private String tickerMsg = null;
    private boolean showTicker = false;
    private boolean showHotspot = false;
    private String hotspotFileName=null;
    public String getDefaultFileName() {
        return defaultFileName;
    }
    public boolean isToDownloadDeafultFiles() {
        return isToDownloadDeafultFiles;
    }
    public void setToDownloadDeafultFiles(boolean isToDownloadDeafultFiles) {
        this.isToDownloadDeafultFiles = isToDownloadDeafultFiles;
    }
    private String fileNames;
    private DataModelManager() {
    }
    public static DataModelManager getInstance() {
        if (dataModelManager == null) {
            synchronized (DataModelManager.class) {
                if (dataModelManager == null) {
                    dataModelManager = new DataModelManager();
                }
            }
        }
        return dataModelManager;
    }
    private synchronized void addImageData(FrameData frameData) {
        //Log.d("Frame Data","Start date "+frameData.getStartDate()+ " " +"end date "+frameData.getEndDate());
        listFrameData.add(frameData);
    }
    public synchronized void parseData(String jsonStr) throws JSONException {
        listFrameData.clear();
        if (jsonStr == null) {
            return;
        }
        List<String> listFileNames = new ArrayList<String>();
        JSONArray jsonArr = new JSONArray(jsonStr);
        int length = jsonArr.length();
        for (int i = 0; i < length; i++) {
            JSONObject jsonObj = jsonArr.getJSONObject(i);
            dataModelManager.addImageData(new FrameData(jsonObj.optString("filename", ""), jsonObj.optString("start", ""), jsonObj.optString("end", ""), jsonObj.optString("filetype", ""), jsonObj.optString("playTime", ""), jsonObj.optBoolean("allDay", false)));
            listFileNames.add(jsonObj.optString("filename", ""));
        }
        fileNames = listFileNames.toString();
    }
    public void setDefaultFileData(String jsonStr) throws JSONException {
        JSONObject jsonObj = new JSONObject(jsonStr);
        defaultFileName = jsonObj.optString("default_image", "");
        screensaverName = jsonObj.optString("default_screensaver ", "");
    }
    @Override
    public String toString() {
        return fileNames.replace("[", "").replace("]", "") + "," + defaultFileName + "," + screensaverName;
    }
    public FrameData getFrameData(int index) {
        return listFrameData.get(index);
    }
    public synchronized List<FrameData> getCurrentDataToShow() {
        List<FrameData> lisCurrDataToShow = new ArrayList<FrameData>();
//        for (FrameData fd : listFrameData) {//concurrent modification exception
            //todo iterator test
            Iterator<FrameData> iterator = listFrameData.iterator();
            while (iterator.hasNext()) {
                FrameData fd = iterator.next();
            long currentTimeInMillis = java.lang.System.currentTimeMillis();
            if ((currentTimeInMillis > fd.getStartDate().getTime() && currentTimeInMillis < fd.getEndDate().getTime()) || (fd.isAllDay() && DateUtils.isToday(fd.getStartDate().getTime()))) {
                if (new File(ImageFrameActivity.ROOT_FOLDER_FILES + fd.getFileName()).exists()) {
                    lisCurrDataToShow.add(fd);
                }
            }
        }
        if (lisCurrDataToShow.size() == 0) {
            lisCurrDataToShow.add(new FrameData(defaultFileName, null, null, null, String.valueOf(120), false));
        }
        return lisCurrDataToShow;
    }
    public String getCurrentFileNames() {
        String currFileNames = "";
        List<FrameData> currFrameData = getCurrentDataToShow();
        for (FrameData data : currFrameData) {
            currFileNames += "," + data.getFileName();
        }
        return currFileNames;
    }
    public ImageFrameActivity getImageFrameAct() {
        return imageFrameAct;
    }
    public void setImageFrameAct(ImageFrameActivity imageFrameAct) {
        this.imageFrameAct = imageFrameAct;
    }

}