Skip to content

Commit 1eac488

Browse files
author
Vincent Potucek
committed
dedicate class CheckThreadSafetyThread from CheckThreadSafetyMojo for concern checkThreadSafety
1 parent 96efade commit 1eac488

1 file changed

Lines changed: 68 additions & 54 deletions

File tree

  • its/core-it-support/core-it-plugins/maven-it-plugin-active-collection/src/main/java/org/apache/maven/plugin/coreit

its/core-it-support/core-it-plugins/maven-it-plugin-active-collection/src/main/java/org/apache/maven/plugin/coreit/CheckThreadSafetyMojo.java

Lines changed: 68 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@
2626
import java.util.Map;
2727
import java.util.Properties;
2828
import java.util.Vector;
29+
import java.util.concurrent.CountDownLatch;
2930

3031
import org.apache.maven.plugin.AbstractMojo;
3132
import org.apache.maven.plugin.MojoExecutionException;
3233
import org.apache.maven.plugins.annotations.Component;
3334
import org.apache.maven.plugins.annotations.LifecyclePhase;
3435
import org.apache.maven.plugins.annotations.Mojo;
3536
import org.apache.maven.plugins.annotations.Parameter;
37+
import org.apache.maven.plugin.logging.Log;
3638

3739
/**
3840
* Checks the thread-safe retrieval of components from active component collections.
@@ -42,6 +44,7 @@
4244
@Mojo(name = "check-thread-safety", defaultPhase = LifecyclePhase.VALIDATE)
4345
public class CheckThreadSafetyMojo extends AbstractMojo {
4446

47+
private static final String MAVEN_CORE_IT_LOG = "[MAVEN-CORE-IT-LOG] ";
4548
/**
4649
* Project base directory used for manual path alignment.
4750
*/
@@ -70,86 +73,97 @@ public class CheckThreadSafetyMojo extends AbstractMojo {
7073
* Runs this mojo.
7174
*
7275
* @throws MojoExecutionException If the output file could not be created.
76+
*
77+
* @implNote threads need to use different realms to trigger changes of the collections.
7378
*/
7479
public void execute() throws MojoExecutionException {
75-
Properties componentProperties = new Properties();
76-
77-
getLog().info("[MAVEN-CORE-IT-LOG] Testing concurrent component access");
78-
79-
ClassLoader pluginRealm = getClass().getClassLoader();
80-
ClassLoader coreRealm = MojoExecutionException.class.getClassLoader();
81-
82-
final Map map = componentMap;
83-
final List list = componentList;
84-
final List go = new Vector();
85-
final List exceptions = new Vector();
86-
87-
Thread[] threads = new Thread[2];
80+
getLog().info(MAVEN_CORE_IT_LOG + "Testing concurrent component access");
81+
final Thread[] threads = new Thread[2];
82+
final List<Exception> exceptions = new Vector<>();
83+
final CountDownLatch startLatch = new CountDownLatch(1);
8884
for (int i = 0; i < threads.length; i++) {
89-
// NOTE: The threads need to use different realms to trigger changes of the collections
90-
final ClassLoader cl = (i % 2) == 0 ? pluginRealm : coreRealm;
91-
threads[i] = new Thread() {
92-
private final ClassLoader tccl = cl;
93-
94-
public void run() {
95-
getLog().info("[MAVEN-CORE-IT-LOG] Thread " + this + " uses " + tccl);
96-
Thread.currentThread().setContextClassLoader(tccl);
97-
while (go.isEmpty()) {
98-
// wait for start
99-
}
100-
for (int j = 0; j < 10 * 1000; j++) {
101-
try {
102-
for (Object o : map.values()) {
103-
o.toString();
104-
}
105-
for (Object aList : list) {
106-
aList.toString();
107-
}
108-
} catch (Exception e) {
109-
getLog().warn("[MAVEN-CORE-IT-LOG] Thread " + this + " encountered concurrency issue", e);
110-
exceptions.add(e);
111-
}
112-
}
113-
}
114-
};
85+
threads[i] = new Thread(new CheckThreadSafetyTask(
86+
(i % 2) == 0 ? getClass().getClassLoader() : MojoExecutionException.class.getClassLoader(),
87+
startLatch,
88+
componentMap,
89+
componentList,
90+
exceptions,
91+
getLog()
92+
));
11593
threads[i].start();
11694
}
11795

118-
go.add(null);
96+
startLatch.countDown(); // signal all threads to start
97+
joinOrInterrupt(threads);
98+
storeComponentProperties(exceptions);
99+
getLog().info(MAVEN_CORE_IT_LOG + "Created output file " + outputFile);
100+
}
101+
102+
private void joinOrInterrupt(Thread[] threads) {
119103
for (Thread thread : threads) {
120104
try {
121105
thread.join();
122106
} catch (InterruptedException e) {
123-
getLog().warn("[MAVEN-CORE-IT-LOG] Interrupted while joining " + thread);
107+
Thread.currentThread().interrupt();
108+
getLog().warn(MAVEN_CORE_IT_LOG + "Interrupted while joining " + thread);
124109
}
125110
}
111+
}
126112

113+
private void storeComponentProperties( List<Exception> exceptions) throws MojoExecutionException {
114+
final Properties componentProperties= new Properties();
127115
componentProperties.setProperty("components", Integer.toString(componentList.size()));
128116
componentProperties.setProperty("exceptions", Integer.toString(exceptions.size()));
129117

130118
if (!outputFile.isAbsolute()) {
131119
outputFile = new File(basedir, outputFile.getPath());
132120
}
133121

134-
getLog().info("[MAVEN-CORE-IT-LOG] Creating output file " + outputFile);
135-
136-
OutputStream out = null;
137-
try {
122+
getLog().info(MAVEN_CORE_IT_LOG + "Creating output file " + outputFile);
123+
try (OutputStream out = new FileOutputStream(outputFile)) {
138124
outputFile.getParentFile().mkdirs();
139-
out = new FileOutputStream(outputFile);
140125
componentProperties.store(out, "MAVEN-CORE-IT-LOG");
141126
} catch (IOException e) {
142127
throw new MojoExecutionException("Output file could not be created: " + outputFile, e);
143-
} finally {
144-
if (out != null) {
128+
}
129+
}
130+
131+
private record CheckThreadSafetyTask(
132+
ClassLoader tccl,
133+
CountDownLatch startLatch,
134+
Map<String, TestComponent> map,
135+
List<TestComponent> list,
136+
List<Exception> exceptions,
137+
Log log
138+
) implements Runnable {
139+
140+
@Override
141+
public void run() {
142+
log.info(MAVEN_CORE_IT_LOG + "Thread " + Thread.currentThread() + " uses " + tccl);
143+
Thread.currentThread().setContextClassLoader(tccl);
144+
try {
145+
startLatch.await(); // wait for the start signal
146+
checkThreadSafety();
147+
} catch (InterruptedException e) {
148+
Thread.currentThread().interrupt();
149+
log.warn(MAVEN_CORE_IT_LOG + "Thread " + Thread.currentThread() + " was interrupted while waiting");
150+
}
151+
}
152+
153+
private void checkThreadSafety() {
154+
for (int j = 0; j < 10 * 1000; j++) {
145155
try {
146-
out.close();
147-
} catch (IOException e) {
148-
// just ignore
156+
for (Object o : map.values()) {
157+
o.toString();
158+
}
159+
for (Object aList : list) {
160+
aList.toString();
161+
}
162+
} catch (Exception e) {
163+
log.warn(MAVEN_CORE_IT_LOG + "Thread " + Thread.currentThread() + " encountered concurrency issue", e);
164+
exceptions.add(e);
149165
}
150166
}
151167
}
152-
153-
getLog().info("[MAVEN-CORE-IT-LOG] Created output file " + outputFile);
154168
}
155-
}
169+
}

0 commit comments

Comments
 (0)