我实现了一个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)的最佳方法是什么,而不必每天都有数千个线程启动造成的开销?
答案 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);