In my application I have code which should run every hour on a new items and execute some expensive operation with multithreading:
int i = 1;
//noinspection InfiniteLoopStatement
while (true) {
try {
Logger.printIterationNum("Text analysis", "beg", i);
Document query = new Document("fetchStatus", new Document("$lte", fetchStatusParam));
ArrayList<Document> unfetchedEvents = dbC_Events.find(query).projection(
fields(include("_id"), include("link"), include("title"), include("summary"))
).into(new ArrayList<>());
// get full text and images of the events
this.getFullTextImg(dbC_Events, unfetchedEvents);
Logger.printIterationNum("Text analysis", "end", i++);
// make a pause between executions
Pauser.rest(Pauser.Units.SECONDS, PAUSE_TIME_OUT);
} catch (Exception e) {
i = 1;
e.printStackTrace();
}
}
private void getFullTextImg(MongoCollection<Document> dbC_Events, ArrayList<Document> unfetchedEvents) {
int cpuCoresNum = SYS_MAX_NUM_CPU_CORES;
int itemsPerCore = unfetchedEvents.size() / cpuCoresNum;
// prevent infinite thread generation if num of unfetched events is less than number of CPU cores
if (itemsPerCore == 0) {
itemsPerCore = unfetchedEvents.size();
}
// update status of queried items
DBAgent.updateItemsStatus(dbC_Events, unfetchedEvents, FetchStatus.IN_PROCESS_FETCH.getID());
int itNum = 1;
int upperIndex = 0;
ExecutorService service = Executors.newFixedThreadPool(cpuCoresNum);
for (int i = 0; i < unfetchedEvents.size(); i += itemsPerCore) {
int indexFrom = i;
upperIndex += itemsPerCore;
int toIndex = upperIndex;
if (((unfetchedEvents.size() - toIndex) <= itemsPerCore) && (itNum == cpuCoresNum)) {
toIndex = unfetchedEvents.size();
i = unfetchedEvents.size();
}
int indexTo = toIndex;
int treadID = itNum++;
service.execute(() -> {
try {
Thread.currentThread().setName("im_evFullTextImg_#" + String.format("%03d", treadID));
this.fetcher(dbC_Events, new ArrayList<>(unfetchedEvents.subList(indexFrom, indexTo)));
} catch (Exception e) {
e.printStackTrace();
}
});
}
// wait until all threads will be finished
service.shutdown();
try {
service.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
My questions:
Is it a good idea to initialize the
Executors.newFixedThreadPool(cpuCoresNum)
each time I execute thegetFullTextImg()
method, or is it better to initialize it once and pass it as a parameter each time I callgetFullTextImg()
?If I initialize
Executors.newFixedThreadPool(cpuCoresNum)
out ofgetFullTextImg()
and pass it as a paramete, will it cause some issues since I useservice.shutdown();
, which prevents accepting new tasks to the thread pool?If
service.shutdown();
is a problematic to reuse the thread pool, how can I redesign it in order to still wait until all threads in a poll will be finished, and only after to continue the code flow?Can the
Executors.newFixedThreadPool(cpuCoresNum)
reuse lead to memory leak issues? Is there some important thing I have to do (e.g. clean the pool) with the thread pool in order to reuse it?