【发布时间】:2013-08-27 14:23:47
【问题描述】:
我的应用程序中有一个进程通过 Servlet 将文档上传到我的服务器并等待完成,然后服务器使用 2 个线程处理文件,并在运行时保留 Status。
Status 类的外观如下:
class Status implements Serializable {
private Integer read;
private Integer validated = 0;
private Integer processed = 0;
private Integer failed = 0;
public Status (int read) {
this.read = read;
}
/*
* Getter methods go here.
* No Setter methods.
*/
public void incrementValidated() {
synchronized(validated) { validated++; }
}
public void incrementProcessed() {
synchronized(processed) { processed++; }
}
public void incrementFailed() {
synchronized(failed) { failed++; }
}
}
现在,服务器以这种方式处理文件:
- 线程根据 DB 值验证读取的行,将正常的行放入队列中。
- 线程一直等待,直到队列中有一批项目,然后将这批 X 项目持久化。
当项目正常 (incrementValidated)、项目持久化 (incrementProcessed) 和项目无效 (incrementFailed) 时更新 Status。
Status存储在一个ConcurrentHashMap<String, Status>中,其中key是用户的sessionID(因为这个进程可以处理多个请求)。
当进程运行时,客户端也在通过 Servlet 轮询服务器,它所做的只是return statusMap.get(sessionId);,直到进程完成。
我的问题出在运行时间过长的文件上,例如 5 分钟。当它运行并轮询服务器以获取状态时,有时所有值都设置回 0,唯一保持不变的值是 read 属性。
我不确定这怎么可能,因为该对象没有设置器,所以我只能想象该对象正在 re-instantiated 在构造函数上使用相同的值,因此保持相同的值。
这可能吗?还是我错过了什么?
(发生这种情况时,地址似乎发生了变化)
【问题讨论】:
-
不,对象不能就地“重新实例化”。此外,您应该在
Status类中使用int原始类型而不是Integer。 -
你检查过你的servlet容器的配置吗?是不是你有一个 servlet 池而不是一个?
-
你能贴出servlet的代码,即创建和修改状态的实体吗?
标签: java multithreading servlets