Skip to content

Commit c41677e

Browse files
committed
Use Virtual Threads on Java 21+
1 parent 68a5867 commit c41677e

File tree

14 files changed

+227
-25
lines changed

14 files changed

+227
-25
lines changed

.github/workflows/check-build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
timeout-minutes: 30
2828
strategy:
2929
matrix:
30-
java: [17, 21, 25]
30+
java: [21, 25]
3131
distribution: [temurin]
3232
os: [ubuntu-latest, windows-latest] # Windows is needed for recursive NTFS junctions
3333
runs-on: ${{ matrix.os }}
@@ -76,7 +76,7 @@ jobs:
7676
timeout-minutes: 15
7777
strategy:
7878
matrix:
79-
java: [17]
79+
java: [21]
8080
distribution: [temurin]
8181
steps:
8282
- uses: actions/checkout@v5
@@ -112,7 +112,7 @@ jobs:
112112
timeout-minutes: 15
113113
strategy:
114114
matrix:
115-
java: [17]
115+
java: [21]
116116
distribution: [temurin]
117117
steps:
118118
- uses: actions/checkout@v5

.github/workflows/release.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- name: Set up JDK
2424
uses: actions/setup-java@v5
2525
with:
26-
java-version: '17'
26+
java-version: '21'
2727
distribution: 'temurin'
2828

2929
# Try to reuse existing cache from check-build
@@ -127,7 +127,7 @@ jobs:
127127
uses: actions/setup-java@v5
128128
with: # running setup-java overwrites the settings.xml
129129
distribution: 'temurin'
130-
java-version: '17'
130+
java-version: '21'
131131
server-id: github-central
132132
server-password: PACKAGES_CENTRAL_TOKEN
133133
gpg-passphrase: MAVEN_GPG_PASSPHRASE
@@ -144,7 +144,7 @@ jobs:
144144
uses: actions/setup-java@v5
145145
with: # running setup-java again overwrites the settings.xml
146146
distribution: 'temurin'
147-
java-version: '17'
147+
java-version: '21'
148148
server-id: sonatype-central-portal
149149
server-username: MAVEN_CENTRAL_USERNAME
150150
server-password: MAVEN_CENTRAL_TOKEN
@@ -174,7 +174,7 @@ jobs:
174174
- name: Setup - Java
175175
uses: actions/setup-java@v5
176176
with:
177-
java-version: '17'
177+
java-version: '21'
178178
distribution: 'temurin'
179179

180180
# Try to reuse existing cache from check-build

.github/workflows/test-deploy.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
uses: actions/setup-java@v5
1818
with: # running setup-java overwrites the settings.xml
1919
distribution: 'temurin'
20-
java-version: '17'
20+
java-version: '21'
2121
server-id: github-central
2222
server-password: PACKAGES_CENTRAL_TOKEN
2323
gpg-passphrase: MAVEN_GPG_PASSPHRASE
@@ -34,7 +34,7 @@ jobs:
3434
uses: actions/setup-java@v5
3535
with: # running setup-java again overwrites the settings.xml
3636
distribution: 'temurin'
37-
java-version: '17'
37+
java-version: '21'
3838
server-id: sonatype-central-portal
3939
server-username: MAVEN_CENTRAL_USERNAME
4040
server-password: MAVEN_CENTRAL_TOKEN

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# 2.2.2
1+
# 2.3.0
2+
* Use Virtual Threads on Java 21+
23
* Minor optimizations
34
* Updated dependencies
45

testcontainers-advanced-imagebuilder/pom.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,28 @@
141141
<groupId>org.apache.maven.plugins</groupId>
142142
<artifactId>maven-compiler-plugin</artifactId>
143143
<version>3.14.1</version>
144+
<executions>
145+
<execution>
146+
<id>compile-java-17</id>
147+
<goals>
148+
<goal>compile</goal>
149+
</goals>
150+
</execution>
151+
<execution>
152+
<id>compile-java-21</id>
153+
<phase>compile</phase>
154+
<goals>
155+
<goal>compile</goal>
156+
</goals>
157+
<configuration>
158+
<release>21</release>
159+
<compileSourceRoots>
160+
<compileSourceRoot>${project.basedir}/src/main/java21</compileSourceRoot>
161+
</compileSourceRoots>
162+
<multiReleaseOutput>true</multiReleaseOutput>
163+
</configuration>
164+
</execution>
165+
</executions>
144166
<configuration>
145167
<release>${maven.compiler.release}</release>
146168
<compilerArgs>

testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/AdvancedImageFromDockerFile.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.Optional;
3636
import java.util.Set;
3737
import java.util.concurrent.CompletableFuture;
38+
import java.util.concurrent.ExecutorService;
3839
import java.util.concurrent.TimeUnit;
3940
import java.util.function.BiFunction;
4041
import java.util.function.Consumer;
@@ -66,6 +67,7 @@
6667
import com.github.dockerjava.api.command.BuildImageResultCallback;
6768
import com.github.dockerjava.api.model.BuildResponseItem;
6869

70+
import software.xdev.testcontainers.imagebuilder.concurrent.ImageBuilderExecutorServiceHolder;
6971
import software.xdev.testcontainers.imagebuilder.transfer.DefaultTransferFilesCreator;
7072
import software.xdev.testcontainers.imagebuilder.transfer.DockerFileLineModifier;
7173
import software.xdev.testcontainers.imagebuilder.transfer.FastFilePathUtil;
@@ -488,11 +490,16 @@ protected void prePullDependencyImages(final Set<String> imagesToPull)
488490
imageName,
489491
e.getMessage());
490492
}
491-
}))
493+
}, this.executorServiceForPrePull()))
492494
.toList()
493495
.forEach(CompletableFuture::join);
494496
}
495497

498+
protected ExecutorService executorServiceForPrePull()
499+
{
500+
return ImageBuilderExecutorServiceHolder.instance();
501+
}
502+
496503
protected boolean canImageNameBePulled(final String imageName)
497504
{
498505
// scratch is reserved
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright © 2024 XDEV Software (https://xdev.software)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package software.xdev.testcontainers.imagebuilder.concurrent;
17+
18+
import java.util.concurrent.ExecutorService;
19+
import java.util.concurrent.Executors;
20+
import java.util.concurrent.ThreadFactory;
21+
import java.util.concurrent.atomic.AtomicInteger;
22+
23+
24+
public class DefaultExecutorServiceCreator implements ExecutorServiceCreator
25+
{
26+
@Override
27+
public ExecutorService createUnlimited(final String threadNamePrefix)
28+
{
29+
return Executors.newCachedThreadPool(factory(threadNamePrefix));
30+
}
31+
32+
private static ThreadFactory factory(final String threadNamePrefix)
33+
{
34+
final AtomicInteger nextThreadId = new AtomicInteger(0);
35+
return r -> {
36+
final Thread t = new Thread(r, threadNamePrefix + "-" + nextThreadId.getAndIncrement());
37+
t.setDaemon(true);
38+
return t;
39+
};
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright © 2024 XDEV Software (https://xdev.software)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package software.xdev.testcontainers.imagebuilder.concurrent;
17+
18+
import java.util.concurrent.ExecutorService;
19+
20+
21+
public interface ExecutorServiceCreator
22+
{
23+
ExecutorService createUnlimited(final String threadNamePrefix);
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright © 2024 XDEV Software (https://xdev.software)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package software.xdev.testcontainers.imagebuilder.concurrent;
17+
18+
public final class ExecutorServiceCreatorHolder
19+
{
20+
private static ExecutorServiceCreator instance;
21+
22+
public static ExecutorServiceCreator instance()
23+
{
24+
if(instance == null)
25+
{
26+
init();
27+
}
28+
return instance;
29+
}
30+
31+
private static synchronized void init()
32+
{
33+
if(instance != null)
34+
{
35+
return;
36+
}
37+
instance = new DefaultExecutorServiceCreator();
38+
}
39+
40+
public static void setInstance(final ExecutorServiceCreator instance)
41+
{
42+
ExecutorServiceCreatorHolder.instance = instance;
43+
}
44+
45+
private ExecutorServiceCreatorHolder()
46+
{
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package software.xdev.testcontainers.imagebuilder.concurrent;
2+
3+
import java.util.concurrent.ExecutorService;
4+
5+
6+
/**
7+
* Holds the {@link ExecutorService} that will be used for ImageBuilder related work.
8+
* <p>
9+
* This {@link ExecutorService} should be used in favor of {@link java.util.concurrent.ForkJoinPool#commonPool()} as it
10+
* guarantees better scalability.
11+
* </p>
12+
*/
13+
public final class ImageBuilderExecutorServiceHolder
14+
{
15+
private static ExecutorService instance;
16+
17+
public static ExecutorService instance()
18+
{
19+
if(instance == null)
20+
{
21+
init();
22+
}
23+
return instance;
24+
}
25+
26+
private static synchronized void init()
27+
{
28+
if(instance != null)
29+
{
30+
return;
31+
}
32+
instance = ExecutorServiceCreatorHolder.instance().createUnlimited("ImageBuilder");
33+
}
34+
35+
public static void setInstance(final ExecutorService instance)
36+
{
37+
ImageBuilderExecutorServiceHolder.instance = instance;
38+
}
39+
40+
private ImageBuilderExecutorServiceHolder()
41+
{
42+
}
43+
}

0 commit comments

Comments
 (0)