Per molto tempo ho lavorato quasi esclusivamente con flussi di input / output in java. Tuttavia alcuni anni fa ho iniziato a esplorare anche l'I / O asincrono (ad esempio, in esecuzione su jboss netty).
Tuttavia, quando lavoravo nel mondo degli I / O asincroni, non potevo riutilizzare nessuna delle mie utilità di sincronizzazione. Ho anche dovuto iniziare una libreria piuttosto ampia di nuove utilità di I / O e non ero sicuro se puntare al blocco o al non blocco.
Come sempre ... Ho scritto un'API sopra l'I / O esistente che supporta sia il blocco che il non blocco e le utility sono scritte contro questo.
Tuttavia, poiché I / O è una cosa così pervasiva, non sono sicuro che sia una cosa saggia da fare. Ad esempio, prendi un encoder Base64. Sì, apache ha una versione di I / O di sincronizzazione e sì java 8 ha finalmente un encoder asincrono. Ma avevo bisogno di un encoder che potesse fare entrambe le cose.
Lo stesso vale per quoted-stampabile, deflate, ... e naturalmente dovrebbe funzionare per socket (regular & ssl), file, ... in situazioni single-threaded e multithreading, ... Ho bisogno di utilità per la catena insieme a sorgenti I / O, utilizzo di wrapper I / O basati su delimitatori o fissi, ... Ho bisogno di gestori di protocollo per http, ftp, ...
Molti di questi problemi possono essere espressi in modo neutro rispetto ai blocchi o, dato abbastanza pensiero, potrebbero supportare sia asincrono che sincronizzazione, consentendo un'ampia riusabilità.
In breve: è saggio introdurre un'astrazione sopra l'I / O, forzando praticamente tutte le librerie che lo usano (direttamente o indirettamente) per usarlo anche?
Aggiorna
Al centro ci sono ReadableByteContainer e WritableByteContainer che -per l'occhio più esigente- assomigliano a un incrocio tra I / O del flusso e I / O del canale.
public interface ReadableByteContainer extends Closeable {
public int read(byte [] bytes);
public int read(byte [] bytes, int offset, int length);
}
public interface WritableByteContainer extends Closeable {
public int write(byte [] bytes);
public int write(byte [] bytes, int offset, int length);
public void flush();
}
Uno dei programmi di utilità creati su di esso è l'API "Transcoder":
public interface ByteTranscoder {
public void transcode(ReadableByteContainer in, WritableByteContainer out);
public void flush(WritableByteContainer out);
}
che ti permette di fare qualcosa di simile:
ByteContainer container = IOUtils.newByteContainer();
container = IOUtils.wrap(
container,
TranscoderUtils.wrapOutput(container, new Base64Encoder())
);
container.write("test".getBytes());
System.out.println(new String(IOUtils.toBytes(container)));
Questo codice emetterà i byte codificati base64 di "test".
Il fatto è che Base64Encoder è in grado di codificare i dati in modo asincrono, non bloccherà se il contenitore di output segnala che non sono stati scritti dati né bloccherà se il contenitore di input segnala che non sono disponibili dati. Puoi continuare la transcodifica chiamando di nuovo "transcode ()".
Funziona sia in un contesto jboss netty in cui si ottiene il pezzo del contenuto da parte asincrona e nel mondo dello streaming dove tutto si blocca fino a quando non può leggere / scrivere.