在使用ScheduledExecutorService和无延迟文件读取之间切换

问题描述 投票:2回答:1

为了提供上下文,我正在使用一个相当长的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);
    }
}
java swing bufferedreader filereader scheduledexecutorservice
1个回答
2
投票

据我所知,readFileSlowreadFileFast是相同的。我们假装不是。关键是要有两种方法可以做不同的事情。

然后,让我们稍微修复readFileSlowreadFileFast。我只展示了readFileSlow,另一个看起来是一样的:

public static void readFileSlow(BufferedReader br) throws IOException
{
    String newValue = null;
    while ((newValue = br.readLine()) != null)
    {
        System.out.println(newValue);
        return;
    }
}

发生了什么?

  1. 没有返回类型。如果我们想从ScheduledExecutorService调用它,那么返回的值无论如何都会丢弃。 schedule*方法不返回Future -s来检索结果。如果是计划外阅读,即executorService.submit(),我们可以使用返回值做一些事情。但是不是现在。
  2. 没有String newValue变量。由于该变量是在函数调用(按值传递)中复制的,因此我们可以定义一个具有相同名称的局部变量。结果将是相同的,但意图将更容易理解。

忍受我,我们快到了。

你可以将这些函数调用包装成lambdas,如下所示:

    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);

还有其他几个选项,例如将doSomethingWithActualLine()中的FileReaderTask方法替换为您给构造函数的lambda。你可以选择任何东西 - 取决于你想要做什么。

© www.soinside.com 2019 - 2024. All rights reserved.