Reputation: 717
I have a multi-threaded program which doesn't seem to actually utilize all cores in my machine. Here is the code and any input would be highly appreciated.
Main Class
public class MainClass{
public static void main(String [] args){
Work work=new Work();
work.doIt();
}
}
The second class creates the tasks and hand them to the ExecutorService, here is the pseudo-code
public class Work{
public void doIt() throws InterrputedException, Exception{
map=get some data and put it in the map;
ArrayList<Future<Integer>> list=new ArrayList<Future<Integer>>();
ArrayList<WorkCallable>jobs=new ArrayList<WorkCallable>();
for each entry in the map;
jobs.add(new WorkCallable(entry);
int numCores=Runtime.getRuntime().availableProcessors();
ExecutorService executor=Executors.newFixedThreadPool(numCores);
int size=jobs.size();
for(int i=0;i<size;i++){
Callable<Integer> worker=jobs.get(i);
Future<Integer> submit=executor.submit(worker);
list.add(submit);
}
executor.shutdown();
while(!executor.isTerminated()) {}
do something with the returned data;
}
}
The Callable class
public class WorkCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception{
Properties props=new Properties();
props.put("annotators", "tokenize, ssplit, pos");
StanfordCoreNLP pipeline=new StanfordCoreNLP(props);
for(String id:entry.keySet()){
Annotation document=new Annotation(entry.get(id));
pipeline.annotate(document);
process the data;
return an integer value;
}
}
The problem is that, when I check how many threads are running, I found only very few and it seems that the executor is not taking advantages of ideal cores!
I hope the description is clear.
Update:
Upvotes: 0
Views: 521
Reputation: 159
At this point with the information you have provided I would suspect that there is some contention among threads so probability is that some of threads are blocked/ waiting. To verify this you can use JVisual VM and take thread dump(Jconsole is also an option). JVisual VM is utility to monitor java Application and comes with JDK. If you haven't use that before this would be good investment of your time to learn about it as it is very useful and simple to use.
On other note as pointed out by @Marko you could be more efficient in handling executors shutdown and I would say ExecutorCompletionService would fit your requirement and make code more elegant and easy to read. Check here for ExecutorCompletionService Once you figure out idle cores may be you can refactor to use ECS.
Upvotes: 0
Reputation: 1018
If you are using Windows then the JVM will delegate the thread sheduling the the NT Kernel. POSIX type operating systems map the OS threads directly with the JVM and schedules co-operatively.
However, whatever happens, you won't be able to ensure that the threads are assigned evenly across the cores/processors. Something else on the OS could be running on core 4 when you start your 4th thread, so it might get scheduled towards another core. Or the scheduler could decide to stack them on the same core.
Upvotes: 1