Reputation: 81
I have a List of 100,000 objects. Want to read the List as fast as possible.
Had split them into multiple small List each of 500 objects
List<List<String>> smallerLists = Lists.partition(bigList, 500);
ExecutorService executor = Executors.newFixedThreadPool(smallerLists.size());
for(int i = 0; i < smallerLists.size();i++) {
MyXMLConverter xmlList = new MyXMLConverter(smallerLists.get(i));
executor.execute(xmlList);
}
executor.shutdown();
while (!executor.isTerminated()) {}
MyXMLConverter.java Again using Executors of 50 threads, to process these 500 objects List.
public MyXMLConverter(List<String> data){
this.data = data;
}
@Override
public void run() {
try {
convertLine();
} catch (Exception ex) {}
}
public void convertLine(){
ExecutorService executor = Executors.newFixedThreadPool(50);
for(int i = 0; i < data.size();i++) {
MyConverter worker = new MyConverter(list.get(i));
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {}
}
It's consuming lot of time in fetching the objects from List. Is there any better way to do this ? Please suggest.
Upvotes: 1
Views: 530
Reputation: 20534
There is two main problem
while (!executor.isTerminated()) {}
I suggest to use something like this.
ExecutorService executor = Executors.newFixedThreadPool(COUNT_OF_YOUR_PROCESSOR_CORESS * 2);
List<Future<?>> futureList = new ArrayList<Future<?>>();
for(String currentString : bigList) {
MyConverter worker = new MyConverter(currentString);
Future<?> future = executor.submit(worker);
futureList.add(future);
}
Collections.reverse(futureList);
for (Future<?> future : futureList){
future.get();
}
executor.shutdown(); //No worries. All task already executed here
Or if you Java 8 addict then
bigList.parallelStream().forEach(s -> new MyConverter(s).run());
Upvotes: 1
Reputation: 159135
Since processing time of each item may vary, it'd be better to just have each worker thread pull the next item to processes directly from the main list, in order to keep all threads busy at the end.
Multi-threaded pulling from a shared list is best done using one of the concurrent collections. In your case, ConcurrentLinkedQueue
would be a prime candidate.
So, copy your list into a ConcurrentLinkedQueue
(or build the "list" directly as a queue), and let your threads call poll()
until it return null
.
If building the list of 100000 elements take time too, you can even kickstart the process by allowing worker threads to begin their job while building the queue. For this, you'd use a LinkedBlockingQueue
, and the workers would call take()
.
You'd then add a special element to the queue to mark the end, and when a worker get the end-marker, it would put it back in the queue for the next worker, then exit.
Upvotes: 2