Reputation: 77
I needed to refactor a code to see if it can help me resolve my "Could not open Hibernate Session for transaction". I am currently trying to streamline the way threads are handled in the code.
The existing code is seen as below. Lets call it 'code A':
if (!CollectionUtils.isEmpty(dailyReportProjectList)) {
for (ProjectEntity project : dailyReportProjectList) {
Thread.sleep(2000);
new Thread(() -> {
try {
// Implementation Logic
if (isConfig == true) {
// Generating Daily Report
if (dailyRep != null) {
LOG.info(
"============start of daily report mail for zone : " + zone + ", newZone : "
+ newZone + " for date : " + currOrPrevDay + "===============");
new Thread(() -> {
try {
//genericController;
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
} else {
//"All 4 default reports for site : " + project.getId() + ", empId:" + project.getEmployerId());
}
}
}
LOG.info("End of generateReportByZone >> zone : " + zone);
} catch (Exception e2) {
e2.printStackTrace();
}
}
}).start();
}
}
In order to streamline this I decided to proceed with Executor Service. I referred a few examples and I am confused as to use service.submit() or service.execute(). I am not seeing my intented benefit from the below code. Can you please help me identify any issues with this apporach.
EDIT: Based on the comments, I have simplified the existing code as above. There is a thread called inside the thread which I feel is not achieving much. Is this ok to have such implementation.
I am planning to do the following:
Instead of passing thread, as a parameter in the for loop, make a separate class and have it implement runnable.
public class ReportProcessor implements Runnable {
private int id;
public ReportProcessor (int id){
this.id = id;
}
public void run(){
try {
String currOrPrevDay = new String();
...// write the code in the try element of 'code A' here onwards
In the 'code A' executor. submit the newly created class
for (i = 0; i < dailyReportProjectList.length; i ++){
service.submit(new ReportProcessor(i));
}
But how do I fulfil the dependencies required by the existing stated 'code A' if I separate out the logic to a new class. I am trying to model my executor service on the basis of this tutorial https://www.youtube.com/watch?v=KUdro0G1BV4&t=325s
Upvotes: 2
Views: 2432
Reputation: 107
Do not pass a Thread, pass a lambda or anything "runnable".
ExecutorService service = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int number = i;
service.execute(() -> System.out.println("test" + number));
}
Edit:
I really think this code need simplicity. It seems you want to create reports.
So why create a thread in a Thread ?
And why Thread.sleep ? (generally malpractice, prefer wait/notify)
I do really think you don't need threads at all.
But if you really want (or need) them, loose coupling:
And try Streams and functional interfaces. It will simplify your code.
dailyReportProjectList.parallelStream()
.filter(condition)
.forEach(doSomething)
Streams manage threading themselves.
Upvotes: 2