我创建了10个线程,与循环相比,它需要花费大量时间进行计算。 线程创建所花费的大部分时间。所以我想减少创建线程的时间。有没有减少创建线程的时间的解决方案?
此调用线程和线程创建需要大量时间。我希望减少那个时间或者任何其他方式来快速执行。
class ThreadCheck{
public static int e = 30;
private static int minpt = 1;
private static List<Point> Neighbours = new CopyOnWriteArrayList<Point>();
public static void main(String[] s){
getList();
}
private static void getList() {
List<Point> newList = new CopyOnWriteArrayList<Point>();
newList.clear();
Point p = new Point(10, 15);
try{
FileInputStream fis = new FileInputStream("TotalFollowers.txt");
BufferedReader textReader = new BufferedReader (new InputStreamReader(fis));
String aLine;
while( (aLine = textReader.readLine())!= null )
{
StringTokenizer st = new StringTokenizer(aLine, "\t");
Point np = new Point(Double.parseDouble(st.nextElement()+""), Double.parseDouble(st.nextElement()+""));
newList.add(np);
if(newList.size() == 3000){
System.out.println(System.nanoTime());
ParallelVisit pv = new ParallelVisit(newList, p);
pv.start();
System.out.println(System.nanoTime());
newList = new CopyOnWriteArrayList<Point>();
}
}
new ParallelVisit(newList, p).start();
}catch(Exception e){
System.out.println(e);
}
}
public static synchronized void addNeighbour(Point p){
Neighbours.add(p);
}
}
这是Thread类:
class ParallelVisit extends Thread{
List<Point> pointList;
Point p;
public ParallelVisit(List<Point> pointList, Point p){
this.pointList = pointList;
this.p = p;
}
public static double getDistance (Point p, Point q)
{
double dx = p.getX() - q.getX();
double dy = p.getY() - q.getY();
double distance = Math.sqrt (dx * dx + dy * dy);
return distance;
}
public void run(){
try{
Iterator<Point> points = pointList.iterator();
while(points.hasNext()){
Point q = points.next();
if(getDistance(p,q) <= ThreadCheck.e){
ThreadCheck.addNeighbour(q);
}
}
} catch(ConcurrentModificationException e){
System.out.println(e);
} catch(Exception e){
System.out.println(e);
}
}
}
答案 0 :(得分:2)
您可以使用在创建时使用一定数量的线程初始化的ThreadPoolExecutor(http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html。
答案 1 :(得分:1)
也许是一个线程池,但ParallelVisit
实现Runnable
而不是?
class ParallelVisit implements Runnable {
}
ExecutorService threadPool = Executors.newFixedThreadPool(maxConcurrentThreads);
taskPool.submit(new ParallelVisit(newList, p));
答案 2 :(得分:0)
同步似乎是你的瓶颈。我最近读过*,它会大大减慢方法。
*(Head First Design Patterns; O'Reilly;关于单身人士的章节)
此外:关于“implements Runnable” vs. “extends Thread”,您可能使用简单的Runnable实现
答案 3 :(得分:0)
我为此使用线程池。
通过ThreadPoolExecutor
(http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html)创建线程池。使用LinkedBlockingQueue
作为阻止队列。
队列的runnable对象是你的ParallelVisit
类,除了它的run()
方法是循环轮询队列(使用队列的poll
方法)。 / p>
您的主程序将使用队列的pv.start()
方法将工作(newList
)添加到队列中,而不是调用put()
。
在此处阅读有关线程池和队列的更多信息:
答案 4 :(得分:0)
不要使用它:
private static List<Point> Neighbours = new CopyOnWriteArrayList<Point>();
您已同步访问权限。
创建线程并不昂贵,而是在每次添加,设置等过程中经常重复复制该数组。
也是如此
List<Point> newList = new CopyOnWriteArrayList<Point>();
这只会减慢最大列表的填充速度。 3000元素,无论如何都发生在单个线程中。这必然会在线程启动期间减慢你的速度。
答案 5 :(得分:0)
如果整个点列表不是太大而无法放入内存中,请首先将所有点解析为单个List<Point>
,然后使用并行流过滤中心点周围给定范围内的所有点:
// helper methods
private static double distance(Point p1, Point p2) {
return Math.hypot(p1.getX() - p2.getX(), p1.getY() - p2.getY());
}
private boolean withinDistance(Point p) {
return distance(center, p) <= e;
}
// parallel filtering
Set<Point> result = pointList.parallelStream()
.filter(this::withinDistance)
.collect(Collectors.toSet());
更新:如果点列表不适合内存,您可以将数据源调整为Iterator<Point>
,在调用next()
时逐点解析:< / p>
public class PointParser implements Iterator<Point> {
public PointParser(Reader reader) { ... }
public boolean hasNext() { /* TODO: return true, if more points to parse */ }
public Point next() { /* TODO: parse next point and return it */ }
}
然后您可以使用此Iterator
创建一个流,而无需中间缓冲List
中的所有点:
Iterator<Point> pointIterator = new PointParser();
Spliterator<Point> pointSpliterator = Spliterators.spliteratorUnknownSize(pointIterator, Spliterator.IMMUTABLE | Spliterator.NONNULL);
Set<Point> result = StreamSupport.stream(pointSpliterator, true)
.filter(this::withinDistance)
.collect(Collectors.toSet());