[英]Switch between using ScheduledExecutorService and delay-free File Read
為了提供上下文,我使用了一個相當長的 CSV 文件,其中一列值提供了 1960-2016 年的平均每日溫度,並使用BufferedReader
讀取它們,如下所示:
BufferedReader br = new BufferedReader(new FileReader(new File("src/dailyTemp.csv")));
我還有一個 Swing 應用程序,它提供一個Boolean
值slowSpeed
來聲明是否應該運行ScheduledExecutorService
。 即它是否應該慢/快。
此應用程序的當前目的是簡單地調整下一個讀取的值是立即返回還是按計划返回。
public static void main(String[] args) throws IOException
{
startGraph(); //This is the GUI that provides the state of the slowSpeed variable
final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(Main::readFileSlow, 0, 500, TimeUnit.MILLISECONDS);
BufferedReader br = new BufferedReader(new FileReader(new File("src/dailyTemp.csv")));
String newValue = "";
while (newValue != null)
{
if (slowSpeed)
{
newValue = readFileSlow(newValue, br);
} else
{
newValue = readFileFast(newValue, br);
}
totalCount++;
}
br.close();
System.out.println("FIN");
}
public static String readFileSlow(String newValue, BufferedReader br) throws IOException
{
while ((newValue = br.readLine()) != null)
{
System.out.println(newValue);
return newValue;
}
return null;
}
public static String readFileFast(String newValue, BufferedReader br) throws IOException
{
while ((newValue = br.readLine()) != null)
{
System.out.println(newValue);
return newValue;
}
return null;
}
一個必要的考慮是Reader
不能重新啟動,因此存在while
循環來檢查它。
我遇到的主要問題是readFileSlow()
函數不能接受變量,因為它不是Runnable
並且不能由ScheduledExecutorService
控制。
編輯 1
這是我的原始版本,它合理地展示了切換的工作原理:
public class Main
{
static Boolean slowSpeed = true;
public static void main(String[] args) throws IOException, InterruptedException
{
startGraph();
BufferedReader br = new BufferedReader(new FileReader(new File("src/dailyTemp.csv")));
String newValue;
while ((newValue = br.readLine()) != null)
{
if (slowSpeed)
{
System.out.println(newValue);
doSomething(newValue);
TimeUnit.MILLISECONDS.sleep(500);
} else
{
System.out.println(newValue);
doSomething(newValue);
}
totalCount++;
}
br.close();
System.out.println("FIN");
}
public static void toggleSpeed(Boolean newSpeed)
{
slowSpeed = newSpeed;
System.out.println(slowSpeed);
}
}
據我所知, readFileSlow
和readFileFast
是相同的。 讓我們假裝不是。 關鍵是有兩種方法可以做不同的事情。
然后,讓我們稍微修復readFileSlow
和readFileFast
。 我只顯示readFileSlow
,其他看起來一樣:
public static void readFileSlow(BufferedReader br) throws IOException
{
String newValue = null;
while ((newValue = br.readLine()) != null)
{
System.out.println(newValue);
return;
}
}
發生了什么?
ScheduledExecutorService
調用它,那么無論如何都會丟棄返回的值。 schedule*
方法不返回Future
-s 來檢索結果。 在計划外讀取的情況下,即executorService.submit()
,我們可以對返回值做一些事情。 但是不是現在。String newValue
變量。 由於該變量在函數調用時被復制(按值傳遞),我們可以定義一個具有相同名稱的局部變量。 結果將是相同的,但意圖將更容易理解。耐心等待,我們快到了。
您可以像這樣將這些函數調用包裝到 lambda 中:
final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
final BufferedReader br = new BufferedReader(new FileReader(new File("src/dailyTemp.csv")));
executorService.scheduleAtFixedRate(() -> {
try {
readFileSlow(br);
} catch (IOException e) {
throw new RuntimeException(e);
}
}, 0, 500, TimeUnit.MILLISECONDS);
我們需要try-catch
因為Runnable
不應該拋出已檢查的Exception
-s。 RuntimeException
-s 和Error
-s 沒問題。
您可以對實現Runnable
自定義類執行相同的操作:
private static abstract class FileReaderTask implements Runnable {
protected BufferedReader br;
public FileReaderTask(BufferedReader br) {
this.br = br;
}
protected void doSomethingWithActualLine(String line) {
System.out.println(line);
}
}
private static class SlowFileReaderTask extends FileReaderTask {
public SlowFileReaderTask(BufferedReader br) {
super(br);
}
@Override
public void run() {
try {
String newValue = null;
while ((newValue = br.readLine()) != null)
{
doSomethingWithActualLine(newValue);
return;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
然后你可以像這樣安排它們:
final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
final BufferedReader br = new BufferedReader(new FileReader(new File("src/dailyTemp.csv")));
executorService.scheduleAtFixedRate(new SlowFileReaderTask(br), 0, 500, TimeUnit.MILLISECONDS);
還有其他幾個選項,例如用您提供給構造函數的 lambda 替換FileReaderTask
的doSomethingWithActualLine()
方法。 你可以選擇任何東西——這取決於你想在這里做什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.