转 http://even2012.iteye.com/blog/1963467
一般容器里面涉及到数据的添加移除操作,当出现多线程,就会出现并发修改异常,这个时候就可以加入锁机制
Servlet监听器应用案例—— 自定义session扫描器控制其主动销毁
Demo样例:SessionScanner.java
public class SessionScanner implements HttpSessionListener,ServletContextListener {
private List
private Object lock = new Object();
// Web应用启动时,启动定时器!
public void contextInitialized(ServletContextEvent sce) {
Timer timer = new Timer();
// 定时器任务:每隔30秒就扫描一次集合:是否有Session对象超时,若超时就会被处理(删除)
timer.schedule(new MyTask(list,lock), 0, 30*1000);
}
// Session创建的时候,就被添加到集合里面,进行控制管理
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
System.out.println(session + "被创建了!!");
synchronized (lock) { //锁旗标——防止定时器中删除操作 发生“并发修改异常”。
list.add(session);
}
}
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println(se.getSession() + "被销毁了");
}
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
}
}
// 定时器任务
class MyTask extends TimerTask{
private List list;
private Object lock; //接收锁旗标—— 防止定时器中删除操作 发生“并发修改异常”。
public MyTask(List list,Object lock){
this.list = list;
this.lock = lock;
}
@Override
public void run() {
System.out.println("定时器执行!!");
synchronized (this.lock) {
ListIterator it = list.listIterator();// 此处若使用Iterator,下面在删除操作时,就会发生“并发修改异常”。
while(it.hasNext()){
HttpSession session = (HttpSession) it.next();
if((System.currentTimeMillis()-session.getLastAccessedTime())>30*1000){
session.invalidate();
//list.remove(session); //并发修改异常:ConcurrentModificationException
it.remove();
}
}
}
}
}