我通过读取块(Arraylist)来排序大文件,使用Collections.sort使用自定义比较器对每个arraylist进行排序,并将排序后的结果写入文件,然后对所有文件应用合并排序算法。
我是在一个帖子里做的。
如果我为每个Collections.sort()启动一个新线程,我会获得任何性能提升吗?
我的意思是以下内容:
我从文件读入List,当List已满时,我开始一个新的线程,我对这个List进行排序并写入临时文件。
同时我继续从文件中读取并在列表再次填满时启动一个新线程...
我有另一个问题:
分类更好:
1)我填写的Arraylist,当它完整时,应用collections.sort()
2)我填写的TreeMap,我不需要对它进行排序。 (当我插入项目时,它就是各种各样的)
注意:我使用的是JAVA 1.5
更新: 这是我想要使用的代码,问题是我正在重用使用线程所使用的数据线arraylist而且我需要等到所有线程都完成。 我该如何解决?
int MAX_THREADS = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
List datalines = ArrayList();
try {
while (data != null) {
long currentblocksize = 0;
while ((currentblocksize <= blocksize) && (data = getNext()) != null) {
datalines.add(data);
currentblocksize += data.length();
}
executor.submit(new Runnable() {
public void run() {
Collections.sort(datalines,mycomparator);
vector.add(datalines);
}
});
答案 0 :(得分:0)
使用线程是否会加快速度取决于您是受磁盘I / O还是CPU速度限制。这取决于磁盘的速度(SSD比旋转硬盘快得多),以及比较功能的复杂程度。如果限制是磁盘I / O,则添加线程或担心数据结构没有意义,因为这些不会帮助您更快地从磁盘读取数据。如果限制是CPU速度,你应该首先运行一个探查器,以确保你的比较功能没有做任何缓慢而愚蠢的事情。
答案 1 :(得分:0)
第一个问题的答案是 - 是的。如果实现Merge Sort的并行化版本,您将获得性能提升。更多关于Dr.Dobbs的文章:http://drdobbs.com/parallel/229400239。
答案 2 :(得分:0)
如果您的进程受CPU限制(我怀疑它不是),您可以看到使用多个线程的改进。如果您的进程受IO限制,则需要提高IO带宽和运行速度。
答案 3 :(得分:0)
我建议你实施以下方案,称为农场:
worker0
reader --> worker1 --> writer
...
workerN
因此,一个线程从文件中读取一个块,将其交给工作线程(最佳做法是将工作者作为ExecutorService
)对其进行排序,然后每个工作者将其输出发送到编写器线程放入临时文件。
编辑:好的,我查看了您的代码。要解决共享datalines
的问题,您可以为每个线程创建一个私有成员,该线程存储线程需要排序的当前datalines
数组:
public class ThreadTask implements Runnable {
private List datalines = new ArrayList();
public ThreadTask(List datalines) {
this.datalines.add(datalines);
}
public void run() {
Collections.sort(datalines,mycomparator);
synchronized(vector) {
vector.add(datalines);
}
}
}
您还需要同步对共享vector
集合的访问权限。
然后,等待ExecutorService中的所有线程完成使用:
executor.awaitTermination(30, TimeUnit.SECONDS);
答案 4 :(得分:0)
并行化顺序操作将在三种情况下提高性能:
您描述了案例#3,并确定了测量CPU与IO之间所需的答案。一种方法是使用分析器:如果90%的时间都在FileInputStream.read()
,那么你不太可能获得加速。但是,如果50%的时间在那里,而50%在Arrays.sort()
,那么你将会这样做。
但是,我看到你的一条评论,你说你正在解析比较器内的线条。如果是这种情况,并且Arrays.sort()
需要花费大量时间,那么我愿意打赌通过解析读取可以提高速度。