Fix to use a static threadPool, rather than one per each instance!

This commit is contained in:
2024-06-06 08:15:41 -05:00
parent f7d217a126
commit ec04986434
2 changed files with 65 additions and 8 deletions

View File

@ -23,8 +23,10 @@ package com.kingsrook.qqq.backend.core.actions.tables.helpers;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import com.kingsrook.qqq.backend.core.utils.PrefixedDefaultThreadFactory;
/******************************************************************************* /*******************************************************************************
@ -50,6 +52,9 @@ public class ActionTimeoutHelper
private boolean didTimeout = false; private boolean didTimeout = false;
private static Integer CORE_THREADS = 10;
private static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(CORE_THREADS, new PrefixedDefaultThreadFactory(ActionTimeoutHelper.class));
/******************************************************************************* /*******************************************************************************
@ -75,7 +80,7 @@ public class ActionTimeoutHelper
return; return;
} }
future = Executors.newSingleThreadScheduledExecutor().schedule(() -> future = scheduledExecutorService.schedule(() ->
{ {
didTimeout = true; didTimeout = true;
runnable.run(); runnable.run();

View File

@ -22,10 +22,19 @@
package com.kingsrook.qqq.backend.core.actions.tables.helpers; package com.kingsrook.qqq.backend.core.actions.tables.helpers;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import com.kingsrook.qqq.backend.core.BaseTest; import com.kingsrook.qqq.backend.core.BaseTest;
import com.kingsrook.qqq.backend.core.utils.SleepUtils; import com.kingsrook.qqq.backend.core.utils.SleepUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@ -35,7 +44,18 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*******************************************************************************/ *******************************************************************************/
class ActionTimeoutHelperTest extends BaseTest class ActionTimeoutHelperTest extends BaseTest
{ {
boolean didCancel = false; private static AtomicInteger cancelCount;
/*******************************************************************************
**
*******************************************************************************/
@BeforeEach
void beforeEach()
{
cancelCount = new AtomicInteger(0);
}
@ -45,11 +65,10 @@ class ActionTimeoutHelperTest extends BaseTest
@Test @Test
void testTimesOut() void testTimesOut()
{ {
didCancel = false;
ActionTimeoutHelper actionTimeoutHelper = new ActionTimeoutHelper(10, TimeUnit.MILLISECONDS, () -> doCancel()); ActionTimeoutHelper actionTimeoutHelper = new ActionTimeoutHelper(10, TimeUnit.MILLISECONDS, () -> doCancel());
actionTimeoutHelper.start(); actionTimeoutHelper.start();
SleepUtils.sleep(50, TimeUnit.MILLISECONDS); SleepUtils.sleep(50, TimeUnit.MILLISECONDS);
assertTrue(didCancel); assertEquals(1, cancelCount.get());
assertTrue(actionTimeoutHelper.getDidTimeout()); assertTrue(actionTimeoutHelper.getDidTimeout());
} }
@ -61,25 +80,58 @@ class ActionTimeoutHelperTest extends BaseTest
@Test @Test
void testGetsCancelled() void testGetsCancelled()
{ {
didCancel = false;
ActionTimeoutHelper actionTimeoutHelper = new ActionTimeoutHelper(100, TimeUnit.MILLISECONDS, () -> doCancel()); ActionTimeoutHelper actionTimeoutHelper = new ActionTimeoutHelper(100, TimeUnit.MILLISECONDS, () -> doCancel());
actionTimeoutHelper.start(); actionTimeoutHelper.start();
SleepUtils.sleep(10, TimeUnit.MILLISECONDS); SleepUtils.sleep(10, TimeUnit.MILLISECONDS);
actionTimeoutHelper.cancel(); actionTimeoutHelper.cancel();
assertFalse(didCancel); assertEquals(0, cancelCount.get());
SleepUtils.sleep(200, TimeUnit.MILLISECONDS); SleepUtils.sleep(200, TimeUnit.MILLISECONDS);
assertFalse(didCancel); assertEquals(0, cancelCount.get());
assertFalse(actionTimeoutHelper.getDidTimeout()); assertFalse(actionTimeoutHelper.getDidTimeout());
} }
/*******************************************************************************
** goal here is - confirm that we can have more threads running at same time
** than we have threads allocated to the ActionTimeoutHelper's thread pool,
** and they should all still get cancelled.
*******************************************************************************/
@Test
void testManyThreads() throws InterruptedException, ExecutionException
{
int N = 50;
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<?>> futureList = new ArrayList<>();
for(int i = 0; i < N; i++)
{
System.out.println("Submitting: " + i);
futureList.add(executorService.submit(() ->
{
ActionTimeoutHelper actionTimeoutHelper = new ActionTimeoutHelper(10, TimeUnit.MILLISECONDS, () -> doCancel());
actionTimeoutHelper.start();
SleepUtils.sleep(1, TimeUnit.SECONDS);
}));
}
for(Future<?> future : futureList)
{
future.get();
}
assertEquals(N, cancelCount.get());
}
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/
private void doCancel() private void doCancel()
{ {
didCancel = true; cancelCount.getAndIncrement();
} }
} }