场景如下。
我实现了这样的接口读取:
public interface MessageSourceProvider
{
MessageSource getMessageSource(Locale locale);
}
这个接口有两种实现:一种从静态源中读取,在“构造函数时”完全初始化,另一种不;后一种实现是这样的(expiryEnabled
是一个AtomicBoolean
;评论被删除,完整的源代码在这里;sources
是一个Map<Locale, FutureTask<MessageSource>>
):
@Override
public MessageSource getMessageSource(final Locale locale)
{
if (!expiryEnabled.getAndSet(true))
setupExpiry(expiryDuration, expiryUnit);
FutureTask<MessageSource> task;
synchronized (sources) {
task = sources.get(locale);
if (task == null || task.isCancelled()) {
task = loadingTask(locale);
sources.put(locale, task);
service.execute(task);
}
}
try {
final MessageSource source = task.get(timeoutDuration, timeoutUnit);
return source == null ? defaultSource : source;
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt(); // <-- HERE
return defaultSource;
} catch (ExecutionException ignored) {
return defaultSource;
} catch (TimeoutException ignored) {
task.cancel(true);
return defaultSource;
} catch (CancellationException ignored) {
return defaultSource;
}
}
由于接口本身没有声明抛出InterruptedException
(因为某些实现永远不会这样做),所以我做Thread.currentThread.interrupt()
. 我这样做是为了符合接口。反过来,这个接口的实现在“主”,面向用户的类中使用:
public String getMessage(final Locale locale, final String key)
{
BUNDLE.checkNotNull(key, "query.nullKey");
BUNDLE.checkNotNull(locale, "query.nullLocale");
String ret;
MessageSource source;
for (final Locale l: LocaleUtils.getApplicable(locale))
for (final MessageSourceProvider provider: providers) {
source = provider.getMessageSource(l);
if (source == null)
continue;
ret = source.getKey(key);
if (ret != null)
return ret;
}
// No source found which has the key... Return the key itself.
return key;
}
现在,问题出在FutureTask
. 就像.get()
阻塞一样,InterruptedException
可以抛出一个。并且由于基接口没有声明抛出异常,如果我捕捉到一个我选择恢复线程中断状态。
然而,文学不同意:它说你应该只这样做,或者忽略例外,只有当Thread
你在你自己创造的范围内时。
我的问题是:这是一个面向用户的 API,我目前处理这个问题的方式是否存在潜在问题?如果是,我该如何解决?