Я использую реализацию Consumer Functional Interface, которая обертывает лямбда-выражение и, по-видимому, улавливает любое проверенное исключение и вместо этого выдает непроверенное исключение среды выполнения. Мне это очень нравится, потому что он очищает мои лямбды, и я использую его в ситуации, когда проверенная ошибка в этом случае InterruptedException никогда не будет сгенерирована. Это приемлемо, и если нет, то почему? Ниже приводится реализация интерфейса:
@FunctionalInterface
public interface ThrowingConsumer<T, E extends Throwable> {
void accept(T t) throws E;
static <T, E extends Throwable> Consumer<T> unchecked(ThrowingConsumer<T, E> c){
return t -> {
try{
c.accept(t);
} catch (Throwable e){
throw new RuntimeException();
}
};
}
}
Ниже приводится один пример его использования. Чтобы дать контекст, он берет EntrySet из ConcurrentHashMap, который содержит для ключа идентификатор пользователя и значение Optional BlockingArrayQueue типа Packet, используемое в качестве средства связи с каждым соответствующим пользователем. В этом сценарии я отправляю каждому пользователю пакет, информируя его о том, что сервер ретрансляции вскоре отключится, чтобы дать им возможность полностью закрыть, прежде чем их потоки будут прерваны. Поскольку поток, который их породил, был Main и с тех пор завершил выполнение, а прерывание пришло из ShutdownHook, по-видимому, не может произойти другое прерывание.
public class NetworkThread implements Runnable {
private SecureSocketManager secureSocketManager;
private final int tlsPort;
private final ConcurrentHashMap<String, Optional<BlockingQueue<Packet>>> channelMap;
public NetworkThread(SecureSocketManager secureSocketManager, ConcurrentHashMap<String, Optional<BlockingQueue<Packet>>> channelMap, int tlsPort) {
this.secureSocketManager = secureSocketManager;
this.tlsPort = tlsPort;
this.channelMap = channelMap;
}
public void run() {
ExecutorService clientThreads = Executors.newCachedThreadPool();
// SETUP A SECURESOCKETMANAGER INSTANCE AND ESTABLISH A SERVER SOCKET ON DESIRED PORT
try {
SSLServerSocket sslServerSocket = secureSocketManager.getSslServerSocket(tlsPort);
// BEGIN RECEIVING NEW CONNECTION INSTANCES ON THAT PORT AND LOOP
while (!interrupted()) {
try {
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
clientThreads.execute(new ClientThread(sslSocket, channelMap));
} catch (IOException e) {
e.printStackTrace();
}
}
//------------------------------RELEVANT CODE----------------------------------------------
clientThreads.shutdown();
// There should be no second interrupt so having this unchecked lambda wrapper is acceptable
channelMap.entrySet()
.stream()
.filter(e -> e.getValue().isPresent())
.forEach(ThrowingConsumer.unchecked(e -> e.getValue().get() // WRAPPER USE
.put(new Packet(e.getKey(), "",Type.RELAY_SHUTDOWN, "", "" ))));
if(!clientThreads.awaitTermination(3, TimeUnit.MINUTES))
clientThreads.shutdownNow();
//------------------------------------------------------------------------------------------
} catch (IOException | InterruptedException e) {
clientThreads.shutdownNow();
}
}
}
Спасибо