如何减少在java中创建线程的时间

时间:2014-07-25 13:48:53

标签: java multithreading

我创建了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);
        }
    }
}

6 个答案:

答案 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)

我为此使用线程池。

通过ThreadPoolExecutorhttp://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());