MAIN 方法是测试方法,可以忽略,Session类自定一个测试就行.
import java.util.*;
import java.util.concurrent.TimeUnit;
import static java.lang.Thread.NORM_PRIORITY;
/**
* 一个线程安全的容器<br/>
* 添加一个对象到容器中,加上一个执行时间,以及一个key<br/>
* 当时间到达时,且没有被{@link MapQueue#remove(String)}方法移除,将会执行容器的{@link MapQueue#exe(Object)}方法<br/>
* 在任何时间,都可以通过key从容器中移除对象,被移除的对象将不再执行容器指定的方法<br/>
* 注:在exe方法中可以再次调用{@link MapQueue#addWithTimestamp(long, Object, String)}将他再次添加到容器中
* @author guolinyuan
*/
public abstract class MapQueue<T>
{
Queue<A<T>> queue = new PriorityQueue<>();
Map<String,A<T>> map = new HashMap<>();
static class A<E> implements Comparable<A>
{
long time;
E object;
String key;
boolean status;
@Override
public int compareTo(A o)
{
return (int) (this.time - o.time);
}
public A(long time, E object, String key)
{
this.time = time;
this.object = object;
this.key = key;
this.status = true;
}
@Override
public String toString()
{
return "A{" +
"time=" + time +
", object=" + object +
'}';
}
}
public static void main(String[] args) throws InterruptedException
{
MapQueue<Session> mapQueue = new MapQueue<Session>()
{
@Override
void exe(Session o)
{
System.out.println(System.currentTimeMillis() + o.getUserId());
this.addWithTimestamp(System.currentTimeMillis() + 60000,o,o.getUserId());
}
};
Session session1 = new Session();
session1.setUserId("1L");
Session session2 = new Session();
session2.setUserId("2L");
Session session3 = new Session();
session3.setUserId("3L");
mapQueue.addWithTimestamp(System.currentTimeMillis() + 60000,session1,"1L");
mapQueue.addWithTimestamp(System.currentTimeMillis() + 30000,session2,"2L");
mapQueue.addWithTimestamp(System.currentTimeMillis() + 50000,session3,"3L");
mapQueue.remove("2L");
TimeUnit.MINUTES.sleep(2);
mapQueue.remove("3L");
while (true)
{
}
}
public MapQueue()
{
this.run();
}
void run()
{
Thread t = new Thread(new Runnable()
{
@Override
@SuppressWarnings("all")
public void run()
{
while (true)
{
synchronized (this)
{
A<T> head = queue.peek();
if (head != null)
{
//如果头没有被map移除
if (head.status)
{
//如果头到了执行时间
if (head.time <= System.currentTimeMillis())
{
//执行.且从queue和map中同时移除
map.remove(head.key);
exe(queue.poll().object);
}
}
else
{
//失效了直接从队列移除
queue.poll();
}
}
try
{
TimeUnit.MILLISECONDS.sleep(1);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
});
t.setPriority(NORM_PRIORITY - 1);
t.start();
}
public synchronized void remove(String key)
{
map.get(key).status = false;
map.remove(key);
}
public synchronized void addWithTimestamp(long timestamp,T t,String key)
{
A<T> a = new A<T>(timestamp,t,key);
queue.add(a);
map.put(key,a);
}
abstract void exe(T o);
}