У меня есть класс контроллера, перечисленный ниже - все, что он делает - это (для демонстрации моей проблемы) генерирует число, преобразует его в строку, преобразует строку в байты и записывает байты в ответ на вызов API.
API выставляется через HTTP.
Когда я пытаюсь прочитать сообщения из API - он блокирует ожидание записи 8k в поток.Есть ли способ читать менее 8 Кбайт за раз?
Блок операции чтения здесь, в java.net.SocketInputStream # socketRead0, потому что java.net.SocketInputStream # socketRead запрашивает 8 Кбайт.
@Controller
@RequestMapping("/myapi/**")
public class MyApi {
private static Logger logger = LoggerFactory.getLogger(ApiController.class);
private Queue<Byte[]> out = new ArrayBlockingQueue<>(1000);
private AtomicLong nextId = new AtomicLong();
public MyApi() {
new ScheduledThreadPoolExecutor(1).scheduleAtFixedRate(() -> {
final long next = nextId.incrementAndGet();
out.add(toObjectArray(Long.toString(next).getBytes()));
}, 0, 1, TimeUnit.SECONDS);
}
@RequestMapping(path = "/download", method = RequestMethod.GET)
public StreamingResponseBody download() {
return outputStream -> {
while (true) {
if (out.isEmpty()) {
outputStream.write(1);
outputStream.write(new byte[]{0});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
logger.error("Unexpected Error", e);
}
} else {
final Byte[] msg = out.poll();
outputStream.write(msg.length);
outputStream.write(toPrimitiveArray(msg));
}
}
};
}
private byte[] toPrimitiveArray(Byte[] bytes) {
byte[] primitive = new byte[bytes.length];
for (int i = 0; i < bytes.length; i++) {
primitive[i] = bytes[i];
}
return primitive;
}
private Byte[] toObjectArray(byte[] bytes) {
Byte[] primitive = new Byte[bytes.length];
for (int i = 0; i < bytes.length; i++) {
primitive[i] = bytes[i];
}
return primitive;
}
}
public class Main {
public static void main(String[] args) throws Exception {
URL url = new URL("http://localhost:8080/myapi/download");
InputStream stream = url.openStream();
int length = stream.read();
while (length != -1) {
byte[] bytes = new byte[length];
for (int i = 0; i < length; i++) {
bytes[i] = (byte)stream.read();
}
System.out.println(Long.valueOf(new String(bytes)));
length = stream.read();
}
}
}