我很难让我的程序正常运行。简而言之,我的程序由几个初始线程组成: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/