Reputation: 7084
I create scheduller for test handling of RejectedExecutionException:
@Component
public class TestScheduler {
private final TestService testService;
private ExecutorService executorService;
public TestScheduler(TestService testService) {
this.testService = testService;
}
@PostConstruct
public void init() {
executorService = Executors.newFixedThreadPool(5);
}
@Scheduled(fixedRate = 10L)
public void test() {
System.out.println("test");
executorService.execute(testService::print);
}
}
And service with delay 70 seconds:
@Component
public class TestService {
public void print() {
System.out.println("print start");
try {
TimeUnit.SECONDS.sleep(70);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("print end");
}
}
I wait next logic:
executorService.execute(testService::print)
5 timestestService::print
will execute 70 secondsexecute
method will call sixth time I get RejectedExecutionException
But I not get Exception. I have this logs:
test
print start
2018-10-22 11:26:45.543 INFO 5960 --- [ main] c.e.s.SchedullerExceptionsApplication : Started SchedullerExceptionsApplication in 0.661 seconds (JVM running for 1.108)
test
print start
test
print start
test
print start
test
print start
test
...
70 seconds print test
EDIT
In real project I have this code:
@PostConstruct
public void init() {
executorService = Executors.newFixedThreadPool(100, new CustomizableThreadFactory("SendRequestExecutor-"));
}
@Scheduled(fixedDelay = 1000L)
public void sendReady() {
try {
List<Message> messages = messageService.findReadyToSend();
for (Message message : messages) {
message.setStatus(IN_PROCESS);
Message savedMessage = messageService.save(message);
executorService.execute(() -> sendRequestService.send(savedMessage.getGuid()));
}
} catch (Exception e) {
log.error("handle: " + e.getMessage());
}
}
does it mean that this code is wrong? because that can happen so I will change entity to status IN_PROCESS
and when try execute - if executorService
full I do not get exception and executorService
not execute my task?
Upvotes: 0
Views: 117
Reputation:
There are two aspects involved when defining an executor.
Executors.newFixedThreadPool(5)
.newFixedThreadPool
uses an unbounded queue, therefore you do not get an exception.You can achieve your desired behavior by creating your own executor service as follows and submitting 11 tasks to it (5 to use all the threads, 5 to fill the underlying task queue and 1 to overflow it).
new ThreadPoolExecutor(5,
5,
2000L,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(5, true),
new ThreadPoolExecutor.CallerRunsPolicy());
Upvotes: 2
Reputation: 32507
RejectedExecutionException
will be thrown you you overflow tasks queue (and that is unbound right now) while you expect it to be thrown when you schedule more tasks (put it into probably unbounded queue) then you have workers - thats nonsens as this is kind of purpose of worker - to build queue and execute from it.
To test error handling, either mock your executor and throw exception on task submit (preferable), or use limited, bounded, non blocking queue as a backing queue for your executor.
Using mock is the most easy way to do this.
Upvotes: 0