Java同步以避免ConcurrentModificationExceptions?

标签 java synchronization

我很难让我的程序正常运行。简而言之,我的程序由几个初始线程组成:Main、MessageReceiver、Scheduler(使用 Quartz 包)以及 Scheduler 线程调度的两类线程:TraceReader 和 ScheduledEvent。现在,当 TraceReader 被触发时,它会读取一个特殊的跟踪文件并安排事件的开始时间、重复间隔(500 毫秒到 1 秒)和结束时间。目前,大约有 140 个事件可以安排同时触发,这会导致大量 ConcurrentModificationException 错误。现在一些代码:

public class Client { //main class
 public static volatile HashMap<Integer, Request> requests;
 public static class Request{
    String node;
    int file_id;
    long sbyte;
    int length;
    int pc_id;
    public Request(){

    }
 }

 public static synchronized void insertRequest(int req_nr, String node, int file_id, long sbyte, int length, int pc_id) {
    Request tempr = new Request();
    tempr.node = node;
    tempr.file_id = file_id;
    tempr.sbyte = sbyte;
    tempr.length = length;
    tempr.pc_id = pc_id;
    requests.put(req_nr, tempr);                       
 }

public static synchronized void doSynchronized(int req_nr, String node, int file_id, long sbyte, int length, int pc_id) {        
    reqnr++;
    String r = "P" + reqnr + "," + file_id + "," + Long.toString(sbyte) + "," + length;        
    insertRequest(Client.reqnr, node, file_id, sbyte, length, pc_id);        
}

public class ScheduledEvent implements Job {
 public synchronized boolean isRequested(long sbyte, int length, int file_id, String node) {
    Request req;
    Iterator<Integer> it = Client.requests.keySet().iterator();
    while (it.hasNext()) {
        req = Client.requests.get(it.next());
        if (req.node.equals(node) && req.file_id == file_id && hits(req.sbyte, req.length, sbyte, length)) {
            return true;
        }
    }
    return false;
 }  
}

所以我基本上得到 ScheduledEvent 类的 isRequested 方法的错误。由于有超过 100 个并发线程,我认为错误是由于其他线程正在使用 Client.doSynchronized() 而其他线程尝试在 isRequested 方法中迭代请求对象而引起的。有什么方法可以使线程同步访问该对象而不使用阻塞(Thread.join() 等)?

最佳答案

代码的基本问题是您的对象在不同的​​对象(锁)上同步。要解决此问题,不要声明同步方法(在类的对象上同步),而是在请求对象本身上同步:

public class Client { //main class

 public static void insertRequest(int req_nr, String node, int file_id, long sbyte, int length, int pc_id) {
    ...
    synchronized (requests) {
      requests.put(req_nr, tempr);
    }
    ...
 }

public class ScheduledEvent implements Job {
 public boolean isRequested(long sbyte, int length, int file_id, String node) {
    ...
    synchronized (requests) {
      while (it.hasNext()) {
          req = Client.requests.get(it.next());
          if (req.node.equals(node) && req.file_id == file_id && hits(req.sbyte,   req.length, sbyte, length)) {
            return true;
        }
      }
    }
    ...
 }  
}

关于Java同步以避免ConcurrentModificationExceptions?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1493436/

相关文章:

java - 我应该如何在 javaFx 中为类似卡拉 OK 的应用程序突出显示带有音频的文本

data-structures - 矢量时钟与版本矢量的用例是什么?

javascript - 同步发出多个ajax请求

Java队列和线程安全

java - 在 Java Batch 中从读取器获取属性

java - 复合对象的同步方法如何工作

c++ - std::future.get() 有时卡在 os x 中

java - hadoop输入路径指定文件夹范围

java - getMethod 正在缓存并导致内存泄漏

java - jaxb 生成的类中的继承