Java数据记录器

时间:2017-07-05 08:52:41

标签: java multithreading logging concurrency

我实现了一个Java数据记录器,它以精确的时间间隔读取来自不同生产机器的一些数据。为了避免一个调用阻塞以下的调用,我想为每次调用解析器类创建一个新线程

然而,这需要创建许多线程,然后每隔10秒(这是我的读取间隔)停止它们。当解析器获得异常时(由于IoT设备可能会超时),非并发方法会导致我有很多延迟,从而导致下一次调用被延迟。

while(!error){

//JDBC connections and other calls here
//Queryresult is a ResultSet that returns all the machine addresses needing to be read

    while(queryresult.next()){
                        //Parser.ParseSpeedV is the method I need to call concurrently
                        Double v = Parser.ParseSpeedV(..Params..);
                        Double s = v*queryresult.getDouble("const");
                        st = conn.createStatement();
                        st.executeUpdate("INSERT INTO ...");
                    }
st.close();
Thread.sleep(10000);
}

实现并发方法调用(对方法ParseSpeedV)的最佳方法是什么,而不必每天都有数千个线程启动造成的开销?

2 个答案:

答案 0 :(得分:2)

您想要使用的是ScheduledExecutorService。它允许您添加以固定速率或固定延迟重复的任务。所以你可以i.E.添加一个每10秒从设备获取数据的任务。然后Executor服务确保它在该间隔内运行,并且偏差很小。

final ScheduledExecutorService myScheduledExecutor = Executors.newScheduledThreadPool(16);
myScheduledExecutor.scheduleAtFixedRate(myTask, 0L, 10L, TimeUnit.SECONDS);

答案 1 :(得分:0)

您的情况是Thread Pool的完美用例。这部分Java库是在简单Thread之上构建的,它允许您创建一个固定大小的线程池并一遍又一遍地重用它们:

ExecutorService executor = Executors.newFixedThreadPool(5);

任何时候你想做一些工作,你都要把它添加到执行者

executor.execute(new Runnable() {
    @Override
    public void run() {
        // Do some work
    }
});

如果您执行的执行次数超过5次,则额外的可运行程序将保留在队列中,直到有空间。

现在,如果您需要从这些运行任务中接收信息,您需要编写一个实现Runnable的类,并接受某种希望获得您的runnable所具有的信息的对象:

public class Worker implements Runnable {
   Consumer consumer;

   public Worker(Consumer consumer) {
       this.consumer = consumer;
   }

   @Override public void run() {
       // Do work
       value = // get value
       consumer.put(value);
   }
}

现在你所要做的就是定义一个对值进行操作的Consumer类(具有put()方法或其他方法)并创建你的Worker

Consumer consumer = new Consumer();
Worker worker = new Worker(myConsumer);
executor.execute(worker);