我必须在特定时间从 InputStream 读取行并返回我在列表中读取的行。在我当前的解决方案中,我不确定这是否是中断线程的最佳方法,因为有时在返回后会添加一些订单,而有时则不会。
这是我当前的解决方案。
InputStream source;
ObjectMapper objectMapper;
public OrderStreamReader(InputStream source, ObjectMapper objectMapper) {
this.source = source;
this.objectMapper = objectMapper;
}
public List<OrderStream> get( Duration maxTime) {
ExecutorService executor = Executors.newSingleThreadExecutor();
ReaderOrdersStream readerOrder = new ReaderOrdersStream();
Future future = executor.submit(readerOrder::run);
try {
future.get(maxTime.toMillis(), TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
future.cancel(true);
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
} finally {
executor.shutdownNow();
}
return readerOrder.orders;
}
private class ReaderOrdersStream {
private List<OrderStream> orders = new LinkedList<>();
public void run() {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(source))) {
String rawOrder;
while ((rawOrder = bufferedReader.readLine()) != null) {
var currentOrder = objectMapper.readValue(rawOrder, OrderStream.class);
if (Thread.interrupted()) break;
orders.add(currentOrder);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}`
避免退货后额外加单。
如果您在后台线程中启动任务,然后立即等待结果,则使用其他线程根本没有意义。您不妨在第一个线程中执行该任务。
顺便说一句,您没有正确处理关闭执行程序服务。请参阅 Javadoc 中
shutdownAndAwaitTermination
的
ExecutorService
方法中为您提供的样板代码。在Java 19+中,ExecutorService
是AutoCloseable
,所以你可以方便地使用try-with-resources语法来自动关闭执行器服务。
没有线程,只需在读取输入流时检查每个循环的经过时间。
要获取经过的时间,您可以通过调用
System.nanoTime
来计算已经过去的纳秒。但是,当读取 long
的限制时,可以重置该调用返回的不断增加的纳秒计数。达到该限制需要多长时间是未定义的,所以我不会在生产代码中依赖它。
如果微秒分辨率足够的话,获取经过时间的更好方法是使用
Instant
类及其 Instant.now()
方法来捕获当前时刻作为日期时间,偏移量为零小时-分钟-秒来自 UTC 时间子午线。使用 Duration
类来表示未附加到时间线的时间跨度。
record Person( String firstName , String lastName ) { }
ArrayList < Person > persons = new ArrayList <> ( );
Duration maxTime = Duration.ofMillis ( 10 );
InputStream inputStream = null;
Instant start = Instant.now ( );
try (
BufferedReader bufferedReader = …
)
{
String line;
while ( ( line = bufferedReader.readLine ( ) ) != null )
{
Duration elapsed = Duration.between ( start , Instant.now ( ) );
if ( elapsed.toNanos ( ) > maxTime.toNanos ( ) ) break; // If we have exceeded our time limit, break out of this `while`` loop.
String[] parts = line.split ( "," );
String firstName = parts[ 0 ];
String lastName = parts[ 1 ];
Person person = new Person ( firstName , lastName );
persons.add ( person );
}
} catch ( IOException e )
{
throw new RuntimeException ( e );
}