【问题标题】:How can I schedule to recycle the object after several minutes [duplicate]如何安排在几分钟后回收对象[重复]
【发布时间】:2014-09-08 11:02:06
【问题描述】:

我定义了一个类来管理游戏室。当用户创建一个新房间时,我会生成一个具有唯一房间号的新房间并将其添加到哈希集中。

现在,我希望从哈希集中删除那个 Room 对象并回收 Room 对象以解决性能问题,比如 24 小时,否则废弃的 Room 对象将花费我大部分的记忆

我怎样才能做到这一点?此外,任何提高性能的建议都将受到高度赞赏。

我的班级如下:

   public class RoomService {

private RoomService(){
    super();
}

private HashSet<Room> roomSet =new HashSet<Room>();

private static RoomService instance =new RoomService();

public static RoomService getServiceInstance(){
    return instance;
}

private static Integer generateRandom(int length) {
    Random random = new Random();
    char[] digits = new char[length];
    digits[0] = (char) (random.nextInt(9) + '1');
    for (int i = 1; i < length; i++) {
        digits[i] = (char) (random.nextInt(10) + '0');
    }
    return Integer.decode(new String(digits));
}

/**
 * Generate new Room with an unique Room number
 * @return
 */
public Room newRoom(){
    Room newRoom;
    do{
        newRoom =new Room(generateRandom(4));
    }
    while(!roomSet.add(newRoom));

    return newRoom;
}}







public class Room {
private Integer roomNum;
private Date createTime=new Date();
private String creatorId;


/*
 * constructor
 */
public Room(Integer roomNum) {
    super();
    this.roomNum = roomNum;
}




@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((roomNum == null) ? 0 : roomNum.hashCode());
    return result;
}


@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Room other = (Room) obj;
    if (roomNum == null) {
        if (other.roomNum != null)
            return false;
    } else if (!roomNum.equals(other.roomNum))
        return false;
    return true;
}




//getter and setter
//
//
public String getCreatorId() {
    return creatorId;
}

public void setcreatorId(String creatorId) {
    this.creatorId = creatorId;
}

public Integer getRoomNum() {
    return roomNum;
}

public Date getCreateTime() {
    return createTime;
}

}

【问题讨论】:

  • 这正是您所需要的:stackoverflow.com/a/3802420/544983
  • 谢谢!但是我使用的是 Set 而不是地图?他们有什么例子吗?
  • 那你可以看看 guava "cachebuilder" 的例子。
  • 对不起,我不太明白代码。我将该示例复制到我的代码中,并使用 Integer 作为 Key,Customer Class Room 作为 Graph。当我返回时返回 createExpensiveGraph(key);从 CacheLoader 的加载方法中,它说“方法 createExpensiveGraph(Integer) 未定义新 CacheLoader(){} 类型的方法”我还需要做其他事情吗?
  • 将要回收的对象放入队列中,按回收日期排序。将计时器设置为队列中最早的日期。当计时器关闭时,将过期条目出列并执行您为“回收”它们所做的任何事情。 (当然还要重置计时器。)

标签: java algorithm


【解决方案1】:

您可以使用Timer 自己完成此操作。每次有人创建新房间时,您都会创建一个新的TimerTask 实例,该实例将再次删除 id 并安排使用public void schedule(TimerTask task, Date time) 执行该任务。它可能看起来像这样:

private final Timer timer; // Initialised somewhere

public Integer newRoomNum() {
    Integer newRoomNum = ... // Create id
    Date date = ... // Create date when the id should be deleted again
    timer.schedule(new DeleteKeyTask(newRoomNum), date);
    return newRoomNum;
}

其中DeleteKeyTaskTimerTask 的自定义子类,用于删除给定的id。

private class DeleteKeyTask extends TimerTask {
    private final Integer id;

    public DeleteKeyTask(Integer id) {
        this.id = id;
    }

    @Override
    public void run() {
        // remove id
    }

您可以使用不同的方法来节省空间

您可以将日期存储在整数键旁边,而不是每个键都有一个任务。例如,您可以使用HashMap&lt;Integer, Date&gt;(或存储毫秒而不是日期)。地图的键形成您之前的集合。这些值表示密钥被插入或过期的时间。

然后您可以安排计时器删除下一个到期密钥,此时您查找下一个到期密钥并安排删除它等。这将花费您O(n) 时间来计算下一个到期密钥。您的任务的运行方法类似于

public void run() {
    map.remove(id);
    Integer next = ... // Find next expiring key
    timer.schedule(new DeleteKeyTask(next), map.get(next));
}

您需要调整创建方法:

public Integer create() { // Previously newRoomNum()
    Integer newRoomNum = ... // Create id
    Date date = ... // Create date when the id should be deleted again
    if(map.isEmpty()) // Only schedule when empty
        timer.schedule(new DeleteKeyTask(newRoomNum), date);
    map.put(newRoomNum, date);
    return newRoomNum;
}

这样你只需要为每个整数存储一个日期。如果在计算下一个时O(n) 开销对您来说太大,您可以通过使用更多空间来使其更快:使用Queue 并插入新键。该队列将允许您检索下一个到期密钥,从而查找下一个到期密钥O(1)

【讨论】:

  • 谢谢!但我希望我可以回收废弃的房间对象,而每个房间不是都有一个任务非常内存成本吗?
  • @Jaskey 我更新了我的答案以提供有关节省空间的更多信息
  • Samuel ,您能否使用更新日期重构代码以使其成为有效示例?因为在我看来,如果我不想为每个房间都有一个时间任务,我不应该在创建新房间时添加代码“timer.schedule(new DeleteKeyTask...”。;PS。根据你的更新,我决定用一个 Room 对象来包裹房间 Num 和创建日期,以后会更广泛。
  • @Jaskey 我添加了一个新示例,说明如何创建新房间。您可以创建一个复合对象并将其存储在一个集合中,但您应该确保其哈希码是键的哈希码,并且 equals 仅比较键。否则,您的集合中可能会有两个具有相同 ID 和不同到期日期的房间。
  • 谢谢!我使用 eclipse 生成的“equals”和“hashcode”来做到这一点。另外,您的代码对我来说很有意义。我认为,您提到的 Queue 使用起来非常有效,因为我们只需要按顺序排列房间入队,而“下一个到期日期”只需要出队即可。不是吗?您使用地图有什么顾虑吗?
猜你喜欢
  • 2015-05-02
  • 2015-08-31
  • 2023-04-01
  • 2012-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-31
  • 2013-09-11
相关资源
最近更新 更多