首先,“它会崩溃”对所发生的事情的描述很糟糕。有什么例外吗?究竟发生了什么?
第二,你确定要同步访问API吗?如果它提供了 Java API,则很有可能该 API 已经同步,并且不需要您的信号量。
第三,如果你获得了一个信号量,你应该在 finally 块中释放它。这保证它被释放,无论 try 块内发生什么:
ticket.acquire();
try {
...
}
catch (...)
finally {
ticket.release();
}
第四:我不明白while(true) 循环的意义。它循环的唯一时间是出现 InterruptedException 时。并且 InterruptedException 精确地用于向线程发出它应该尽快停止执行的信号。所以你的方法应该抛出这个异常而不是吞掉它。
最后,您应该学习 Java 命名约定并遵守它们。方法以小写字母开头。
如果您确实需要同步访问,那么我将如何重写该方法:
public int readInt(int min, int max) throws QuantisException, InterruptedException {
ticket.acquire();
try {
return quantisReadScaledInt(deviceType.getType(), deviceNumber, min, max);
}
finally {
ticket.release();
}
}
如果要确保只有一个线程可以访问本机库函数,请使用这样的类:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class SingleThreadAccess {
public static final SingleThreadAccess INSTANCE = new SingleThreadAccess();
private ExecutorService executor;
// to be called by ServletContextListener.contextInitialized()
public void init() {
executor = Executors.newSingleThreadExecutor();
}
// to be called by ServletContextListener.contextDestroyed()
public void shutdown() {
executor.shutdown();
try {
executor.awaitTermination(2L,TimeUnit.SECONDS);
}
catch (InterruptedException e) {
}
executor.shutdownNow();
}
public int readInt(int min, int max) throws QuantisException, InterruptedException {
Callable<Integer> task = new Callable<Integer>() {
@Override
public Integer call() throws QuantisException {
return quantisReadScaledInt(deviceType.getType(), deviceNumber, min, max);
}
};
Future<Integer> future = executor.submit(task);
try {
future.get();
}
catch (ExecutionException e) {
unwrap(e);
}
}
private void unwrap(ExecutionException e) throws QuantisException {
Throwable t = e.getCause();
if (t instanceof QuantisException) {
throw (QuantisException) t;
}
throw new RuntimeException(e);
}
}