# Gateway Thread Pools & Task Management (Which One)

**URL:** <https://forum.inductiveautomation.com/t/gateway-thread-pools-task-management-which-one/95973>\
**Category:** Module Development\
**Tags:** ignition81\
**Created:** [September 13, 2024, 8:09pm UTC](https://forum.inductiveautomation.com/t/gateway-thread-pools-task-management-which-one/95973 "2024-09-13T20:09:51Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![cody.tamaki](https://avatars.discourse-cdn.com/v4/letter/c/b487fb/32.png) [@cody.tamaki](https://forum.inductiveautomation.com/u/cody.tamaki)\
**Post date:** [September 13, 2024, 8:09pm UTC](https://forum.inductiveautomation.com/t/gateway-thread-pools-task-management-which-one/95973/1 "2024-09-13T20:09:51Z")

</div>

Hi All,

I see there are ~3 gatewayContext objects that can essentially schedule/execute tasks like a thread pool. I wanted to know if there is an intended use for each of these and which I should be using in my context?

```
    gatewayContext.getExecutionManager() or gatewayContext.createExecutionManager()
    gatewayContext.getScheduledExecutorService();
    gatewayContext.getExecutorService();

```

I have a few different services running that I will need to run tasks periodically (somewhere between 1-60s). Some of these might be very CPU intensive on larger systems. In the past I would just make my own executionManager with the gateway, but is that still the best practice?

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [September 13, 2024, 8:37pm UTC](https://forum.inductiveautomation.com/t/gateway-thread-pools-task-management-which-one/95973/2 "2024-09-13T20:37:40Z")

</div>

There's some tradeoffs to each.

The ExecutionManager gives you some visibility at the gateway level about what's running (right? am I imagining this?), but it's based on a fixed-size thread pool, which can sometimes be an issue when there's a lot of tasks submitted.

I prefer the ExecutorService/ScheduledExecutorService combo, but the trick here is that you need to make sure never to actually perform the blocking work on the ScheduledExecutorService thread. The pattern should look something like:

```python
getScheduledExecutor().schedule(
    () -> getExecutor().execute(() -> ...),
    time,
    TimeUnit.MILLISECONDS
);

```

---

<div class="post-metadata">

**Author:** ![cody.tamaki](https://avatars.discourse-cdn.com/v4/letter/c/b487fb/32.png) [@cody.tamaki](https://forum.inductiveautomation.com/u/cody.tamaki)\
**Post date:** [September 13, 2024, 9:26pm UTC](https://forum.inductiveautomation.com/t/gateway-thread-pools-task-management-which-one/95973/3 "2024-09-13T21:26:48Z")

</div>

Yeah, I think we can categorize the execution manager and it'll give some good diagnostic info. Don't know if that works for the other systems?

Right that's good info because I thought the scheduledExecutor would execute whatever you submitted asynchronously.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [September 13, 2024, 9:55pm UTC](https://forum.inductiveautomation.com/t/gateway-thread-pools-task-management-which-one/95973/4 "2024-09-13T21:55:28Z")

</div>

The scheduled executor service is asynchronous, in that it doesn't block the thread you called it from, but it still has to do that work _somewhere_, and the current implementation is a fixed-size thread pool sized to the number of processors available to the JVM. The 'regular' executor pool is a basic cached thread pool of unbound size. `getExecutionManager()` is a fixed size pool configurable by system prop, defaulting to an arbitrary 12 threads.
