我有一堂课提议翻译实用程序.翻译本身应每30分钟重新加载一次.我为此使用Spring Timer支持.基本上,我的课看起来像:
public interface Translator {
public void loadTranslations();
public String getTranslation(String key);
}
loadTranslations()可能需要很长时间才能运行,因此在运行时仍可以使用旧的翻译.这是通过将翻译加载到本地地图中并在加载所有翻译后更改参考来完成的.
我的问题是:如何确保当一个线程已经在加载翻译时,第二个线程也会尝试运行,它会检测到该线程并立即返回,而不启动第二个更新.
同步方法只会使负载排队…我仍然在Java 1.4上,所以没有java.util.concurrent.
谢谢你的帮助 !
解决方法:
使用某种形式的锁定机制仅在尚未执行任务时执行它.获取锁定令牌必须是一个一步的过程.看到:
/**
* @author McDowell
*/
public abstract class NonconcurrentTask implements Runnable {
private boolean token = true;
private synchronized boolean acquire() {
boolean ret = token;
token = false;
return ret;
}
private synchronized void release() {
token = true;
}
public final void run() {
if (acquire()) {
try {
doTask();
} finally {
release();
}
}
}
protected abstract void doTask();
}
如果任务同时运行,将抛出异常的测试代码:
public class Test {
public static void main(String[] args) {
final NonconcurrentTask shared = new NonconcurrentTask() {
private boolean working = false;
protected void doTask() {
System.out.println("Working: "
+ Thread.currentThread().getName());
if (working) {
throw new IllegalStateException();
}
working = true;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!working) {
throw new IllegalStateException();
}
working = false;
}
};
Runnable taskWrapper = new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
shared.run();
}
}
};
for (int i = 0; i < 100; i++) {
new Thread(taskWrapper).start();
}
}
}