0

I created 10 thread and it take lots of time to doing computation as compared to looping. The most of the time taken by the thread creation. So i want to reduce the time to create the thread. Is there any solution for reducing the time to create a thread?

This call the thread and thread creation takes large amount of time. I want to reduce that time or if any other way to make execution fast.

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);
    }
}

This is the Thread class:

 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);
        }
    }
}
Barranka
  • 20,547
  • 13
  • 65
  • 83
user3795373
  • 13
  • 2
  • 6
  • So your code finds all points from a given set of points that are within a certain radius around a given point? – isnot2bad Jul 25 '14 at 14:31
  • It is possible that all this good advice about thread pooling might help, but don't try anything before you have checked whether getting rid of the CopyOnWriteArrayList improves the situation. – laune Jul 25 '14 at 14:53
  • Is there any way to find all points in a given set in a particular radius? – user3795373 Jul 25 '14 at 15:37

6 Answers6

2

You can use a ThreadPoolExecutor (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html) initialized with a set number of threads when it is created.

Khary Mendez
  • 1,818
  • 1
  • 14
  • 18
1

Perhaps a thread pool, but with ParallelVisit implementing Runnable instead?

class ParallelVisit implements Runnable {
}

ExecutorService threadPool = Executors.newFixedThreadPool(maxConcurrentThreads);
taskPool.submit(new ParallelVisit(newList, p));
Stewart
  • 17,616
  • 8
  • 52
  • 80
  • I used ExecutorService but it didn't reduce time. – user3795373 Jul 25 '14 at 14:55
  • One of the main points of a thread pool is that it saves on thread creation. If you have 500 tasks, and a pool of 100, then you have saved on the creation of 400 threads. Is your statement that "thread creation takes large amount of time" really where your bottle-neck is? – Stewart Jul 25 '14 at 15:00
0

synchronize seems to be your bottle neck. I recently read*, that it slows methods dramatically.

*(Head First Design Patterns; O'Reilly; Chapter about Singletons)

Additionally: in regards to “implements Runnable” vs. “extends Thread” you probably use a simple Runnable implementation

Community
  • 1
  • 1
Phe0nix
  • 157
  • 4
  • 15
  • synchronize method(add() method) takes time when more than one thread want to add element. But rest of the time, it have to take less time. How multithreading take large amount of time than looping? – user3795373 Jul 25 '14 at 14:12
  • My opinion is, that synchronized creates an overhead, which applies on every single call of that method, regardless how many threads use that method. It has to lock the method, execute it and unlock it. I did not want to refer to the time the threads need to wait while one of the others executes the method. – Phe0nix Jul 25 '14 at 14:22
0

I'd use a thread pool for this.

Create the thread pool through ThreadPoolExecutor (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html). Use a LinkedBlockingQueue for the blocking queue.

The runnable object of the queue is your ParallelVisit class, except that its run() method would be a loop polling the queue (using queue's poll method).

Your main program, instead of calling pv.start(), would add the work (newList) to the queue using queue's put() method.

Read more about thread pools and queues here:

kzagar
  • 355
  • 2
  • 4
0

Don't use this:

private static List<Point> Neighbours = new CopyOnWriteArrayList<Point>();

when you have synchronized the access.

It isn't thread creation that is costly, it is the frequently repeated copying of that array during each add, set, etc.

The same is true for

List<Point> newList = new CopyOnWriteArrayList<Point>();

which just slows down the filling of the lists of max. 3000 element, which happens in a single thread anyway. This is bound to slow you down during thread start.

laune
  • 31,114
  • 3
  • 29
  • 42
0

If the entire point list is not too large to fit in memory, parse all points into a single List<Point> first, then use parallel streams to filter all points within a given range around your center 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());

Update: In case the point list does NOT fit into memory, you can adapt your data source to an Iterator<Point> that parses point by point on calling next():

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 */ }
}

Then you can use this Iterator to create a stream without the need to intermediately buffer all points in a 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());
isnot2bad
  • 24,105
  • 2
  • 29
  • 50