Skip to content

Commit

Permalink
feat: customize with thread factory
Browse files Browse the repository at this point in the history
  • Loading branch information
stawirej committed Dec 27, 2023
1 parent 637084b commit 03ae6cc
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
Expand All @@ -18,6 +19,14 @@ public final class MultiThreadsCollider implements AutoCloseable {

private static final long DEFAULT_TIMEOUT = 60;
private static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.SECONDS;
private static final ThreadFactory THREAD_FACTORY =
runnable -> {
Thread thread = new Thread(runnable);
thread.setDaemon(true);
thread.setName("collider-pool-" + thread.getName().toLowerCase());
return thread;
};

private final List<Runnable> runnables;
private final List<Integer> times;
private final ExecutorService executor;
Expand All @@ -40,14 +49,7 @@ private MultiThreadsCollider(
this.runnables = runnables;
this.times = times;
this.threadsCount = threadsCount;
// ThreadFactory threadFactory =
// runnable -> {
// Thread thread = new Thread(runnable);
// thread.setDaemon(true);
// thread.setName("threads-collider-pool-" + thread.getName());
// return thread;
// };
this.executor = Executors.newFixedThreadPool(threadsCount);
this.executor = Executors.newFixedThreadPool(threadsCount, THREAD_FACTORY);
this.spinLock = new AtomicBoolean(true);
this.startedThreadsCount = new AtomicInteger(0);
this.runningThreadsLatch = new CountDownLatch(threadsCount);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package pl.amazingcode.threadscollider.multi;

import static org.assertj.core.api.BDDAssertions.then;
import static pl.amazingcode.threadscollider.multi.MultiThreadsCollider.MultiThreadsColliderBuilder.multiThreadsCollider;

import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.RepeatedTest;

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
final class Deadlock_Scenarios {

private static final int ACTION_THREADS_COUNT = Runtime.getRuntime().availableProcessors() / 2;
private List<Integer> list1;
private List<Integer> list2;

private void update1(List<Integer> list1, List<Integer> list2) {

synchronized (list1) {
list1.add(1);
synchronized (list2) {
list2.add(1);
}
}
}

private void update2(List<Integer> list2, List<Integer> list1) {

synchronized (list2) {
list2.add(1);
synchronized (list1) {
list1.add(1);
}
}
}

@BeforeEach
void setUp() {
list1 = new ArrayList<>();
list2 = new ArrayList<>();
}

@RepeatedTest(10)
void Detect_deadlock() {
// Given
List<Exception> exceptions = new ArrayList<>();

// When
try (MultiThreadsCollider collider =
multiThreadsCollider()
.withAction(() -> update1(list1, list2))
.times(ACTION_THREADS_COUNT)
.withAction(() -> update2(list2, list1))
.times(ACTION_THREADS_COUNT)
.withThreadsExceptionsConsumer(exceptions::add)
.withAwaitTerminationTimeout(100)
.asMilliseconds()
.build()) {

collider.collide();
}

// Then
then(exceptions).isEmpty();
}
}

0 comments on commit 03ae6cc

Please sign in to comment.