创建在后台执行特定任务的工作线程
Create worker thread which performs specific task in the background
根据我的项目,
已通过查询从数据库中获取数据,
结果集上有一个Iterator,这个结果集一直在不断的添加数据。
通过遍历 Iterator 对象,结果被添加到 ArrayList
。
一旦我们获得所有条目(超过 200000),然后将其写入文件。
但是由于它使用了更多的 jvm 堆space,我需要使用一个在后台运行的工作线程并将数据写入文件。
由于我是多线程新手,
我想通过创建 1 个线程的固定线程池来使用 Executor 服务,每当条目达到 50000 的计数时,然后将这些条目提交给执行程序以将它们附加到文件中。
请告诉我这种方法是否合适,或者我是否需要遵循任何其他方法。
我认为您不需要 ThreadPool
来处理单线程。您可以通过创建单个线程(伪代码)来做到这一点:
List<Entry> list = new ArraList<Entry>(); // class member that will hold the entries from Result set. I Assume entry as `Entry` here
....
void addEntry(Entry entry){
list.add(entry);
if(list.size() >= 20000){
//assign current list to a temp list inorder to reinitialze the list for next set of entries.
final List tempList = list;// tempList has 20000 entries!
list = new ArraList<Entry>();// list is reinitialized
// initiate a thread to write tempList to file
Thread t = new Thread(new Runnable(){
public void run() {
// stuff that will write `tempList` to file
}});
t.start();// start thread for writing.It will be run in background and
//the calling thread (from where you called `addEntry()` )will continue to add new entries to reinitialized list
}//end of if condition
}
注意:你提到了堆space - 即使我们使用线程它仍然使用堆。
在线程中执行进程将释放主线程来做其他事情。
它不会解决您的堆 space 问题。
堆 space 问题是由查询中 return 的条目数引起的。您可以将查询更改为 return 只有一定数量的行。处理它并从您处理的最后一行开始再次执行查询。
如果您使用的是 MS SQL,这里已经有关于如何拆分您的查询的答案。
Row offset in SQL Server
您不需要在将所有 20000
条目写入文件之前获取它们,除非它们彼此之间存在某些依赖关系。
在最简单的情况下,您可以在获取条目时将条目直接写入文件,从而无需大量堆。
它的高级版本是生产者-消费者模式,然后您可以对其进行调整以获得不同的speed/memory使用特性。
创建工作线程,在获取条目之前处理 beckground.Starting 此线程中的条目,并在完成获取所有条目后停止它,
public class WriteToOutputFile implements Runnable{
BlockingQueue<entry> queue;
File file;
volatile boolean processentries;
WriteToOutputFile(BlockingQueue queue,File file){
this.queue = queue;
this.file = file;
this.processentries= tue;
}
@override
public void run(){
while(processentries && !queue.isEmpty()){
entry = queue.take();
if (entry== lastentry)break;
//logic to write entries to file
} }
public void stop(){
processentries = false;
queue.put(lastentry);
}
}
根据我的项目,
已通过查询从数据库中获取数据, 结果集上有一个Iterator,这个结果集一直在不断的添加数据。
通过遍历 Iterator 对象,结果被添加到 ArrayList
。
一旦我们获得所有条目(超过 200000),然后将其写入文件。
但是由于它使用了更多的 jvm 堆space,我需要使用一个在后台运行的工作线程并将数据写入文件。
由于我是多线程新手, 我想通过创建 1 个线程的固定线程池来使用 Executor 服务,每当条目达到 50000 的计数时,然后将这些条目提交给执行程序以将它们附加到文件中。
请告诉我这种方法是否合适,或者我是否需要遵循任何其他方法。
我认为您不需要 ThreadPool
来处理单线程。您可以通过创建单个线程(伪代码)来做到这一点:
List<Entry> list = new ArraList<Entry>(); // class member that will hold the entries from Result set. I Assume entry as `Entry` here
....
void addEntry(Entry entry){
list.add(entry);
if(list.size() >= 20000){
//assign current list to a temp list inorder to reinitialze the list for next set of entries.
final List tempList = list;// tempList has 20000 entries!
list = new ArraList<Entry>();// list is reinitialized
// initiate a thread to write tempList to file
Thread t = new Thread(new Runnable(){
public void run() {
// stuff that will write `tempList` to file
}});
t.start();// start thread for writing.It will be run in background and
//the calling thread (from where you called `addEntry()` )will continue to add new entries to reinitialized list
}//end of if condition
}
注意:你提到了堆space - 即使我们使用线程它仍然使用堆。
在线程中执行进程将释放主线程来做其他事情。 它不会解决您的堆 space 问题。
堆 space 问题是由查询中 return 的条目数引起的。您可以将查询更改为 return 只有一定数量的行。处理它并从您处理的最后一行开始再次执行查询。
如果您使用的是 MS SQL,这里已经有关于如何拆分您的查询的答案。
Row offset in SQL Server
您不需要在将所有 20000
条目写入文件之前获取它们,除非它们彼此之间存在某些依赖关系。
在最简单的情况下,您可以在获取条目时将条目直接写入文件,从而无需大量堆。
它的高级版本是生产者-消费者模式,然后您可以对其进行调整以获得不同的speed/memory使用特性。
创建工作线程,在获取条目之前处理 beckground.Starting 此线程中的条目,并在完成获取所有条目后停止它,
public class WriteToOutputFile implements Runnable{
BlockingQueue<entry> queue;
File file;
volatile boolean processentries;
WriteToOutputFile(BlockingQueue queue,File file){
this.queue = queue;
this.file = file;
this.processentries= tue;
}
@override
public void run(){
while(processentries && !queue.isEmpty()){
entry = queue.take();
if (entry== lastentry)break;
//logic to write entries to file
} }
public void stop(){
processentries = false;
queue.put(lastentry);
}
}