gpt4 book ai didi

java - Google App Engine 数据存储中的多线程

转载 作者:行者123 更新时间:2023-11-30 11:11:11 25 4
gpt4 key购买 nike

如何使从数据存储区获取和设置属性的操作线程安全?

目前,我有将任务放入队列的代码,每个任务执行一个任务,然后更新一个名为 numberOfTasks 的属性,该属性是 int 类型。它基本上是获取此属性的当前值并递增它。

然而,当任务在队列中执行时,由于线程问题,最终值并不正确。有时,两个任务试图同时更新属性,因此有时增量没有完成。

有人可以帮助正确完成这项工作吗?

数据存储属性 Getter 方法:

private String doGet(String rowId) throws EntityNotFoundException {
Key egsKey = KeyFactory.createKey(DATASTORE_KIND, rowId);

Entity egsEntity = datastore.get(egsKey);

// schema changed from String to Text type. Transparently handle that here.
Object propertyValue = egsEntity.getProperty(PROPERTY_KEY);

if (propertyValue instanceof String) {
return (String) propertyValue;
}

Text text = (Text) propertyValue;

return text.getValue();
}

数据存储属性 SETTER 方法:

private void doPut(String rowId, List<String> list) {
Entity entity = new Entity(DATASTORE_KIND, rowId);
entity.setProperty(PROPERTY_KEY, list);

datastore.put(entity);
}

Setter 和 Getter 方法:

public synchronized int getPendingUsersForProcessing() {
String pendingUsersForProcessingAsString = null;
try {
pendingUsersForProcessingAsString = doGet(PENDING_USERS_FOR_PROCESSING);
return Integer.valueOf(pendingUsersForProcessingAsString);
} catch (NumberFormatException e) {
throw new IllegalStateException("The num of last batches processed in Datastore is not a number: "
+ pendingUsersForProcessingAsString);
} catch (EntityNotFoundException e) {
return DEFAULT_PENDING_USERS_FOR_PROCESSING;
}
}

/** {@inheritDoc } */
@Override
public synchronized void setPendingUsersForProcessing(int pendingUsersForProcessing) {
doPut(PENDING_USERS_FOR_PROCESSING, String.valueOf(pendingUsersForProcessing));
LOG.info("Number of Pending Users For Processing is set to : " + pendingUsersForProcessing);
}

我尝试更新属性的代码:

int pendingUsers = appProperties.getPendingUsersForProcessing();
int requestUsers = request.getUserKeys().size();
appProperties.setPendingUsersForProcessing(pendingUsers + requestUsers);

最佳答案

这不完全是线程问题,因为您的应用程序可能有多个实例执行任务,而这些实例彼此不了解。所以这是一个争用情况。

关于如何解决它,您有多种选择。

  1. 使用 sharding for your counters .

  2. 与其不断更新同一个实体,不如为每个已完成的任务创建一个新实体,使用任务完成的时间作为 id。这种方法的优点是它创建了一个审计跟踪,你总是可以获得统计数据,比如今天、过去一小时内完成的任务数量等。要计算实体的数量,你可以使用仅键查询,这是几乎免费而且非常快。缺点是编写这些实体的成本较高 - 如果您要完成大量任务,这不是解决方案。

  3. 不是计算任务,而是计算这些任务的结果。例如,如果任务更新用户状态,您可以使用免费且快速的仅键查询来计算处于“待处理”状态的用户数。如果您已经有一个索引属性,您可以将其用作标志来计算已完成的任务,这是一种非常好的方法。

关于java - Google App Engine 数据存储中的多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27504836/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com