Во-первых, « он будет падать » - плохое описание того, что происходит. Любое исключение? Что именно происходит?
Во-вторых, вы уверены, что вам нужно синхронизировать доступ к 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);
}
}