39
39
import java .util .concurrent .Executors ;
40
40
import java .util .concurrent .RejectedExecutionException ;
41
41
import java .util .concurrent .ThreadFactory ;
42
+ import java .util .concurrent .atomic .AtomicReference ;
42
43
import java .util .concurrent .locks .LockSupport ;
43
44
import java .util .stream .Collectors ;
44
45
@@ -75,12 +76,12 @@ void testVirtualThreadStartAndEnd() throws Exception {
75
76
}
76
77
77
78
Map <String , Integer > events = sumEvents (recording );
78
- System .out .println (events );
79
+ System .err .println (events );
79
80
80
81
int startCount = events .getOrDefault ("jdk.VirtualThreadStart" , 0 );
81
82
int endCount = events .getOrDefault ("jdk.VirtualThreadEnd" , 0 );
82
- assertTrue ( startCount == 100 );
83
- assertTrue ( endCount == 100 );
83
+ assertEquals ( 100 , startCount );
84
+ assertEquals ( 100 , endCount );
84
85
}
85
86
}
86
87
@@ -89,35 +90,51 @@ void testVirtualThreadStartAndEnd() throws Exception {
89
90
*/
90
91
@ Test
91
92
void testVirtualThreadPinned () throws Exception {
93
+ Runnable [] parkers = new Runnable [] {
94
+ () -> LockSupport .park (),
95
+ () -> LockSupport .parkNanos (Duration .ofDays (1 ).toNanos ())
96
+ };
97
+
92
98
try (Recording recording = new Recording ()) {
93
- recording .enable ("jdk.VirtualThreadPinned" )
94
- .withThreshold (Duration .ofMillis (500 ));
99
+ recording .enable ("jdk.VirtualThreadPinned" );
95
100
96
- // execute task in a virtual thread, carrier thread is pinned 3 times.
97
101
recording .start ();
98
- ThreadFactory factory = Thread .ofVirtual ().factory ();
99
- try (var executor = Executors .newThreadPerTaskExecutor (factory )) {
100
- executor .submit (() -> {
101
- synchronized (lock ) {
102
- // pinned, duration < 500ms
103
- Thread .sleep (1 );
104
-
105
- // pinned, duration > 500ms
106
- Thread .sleep (Duration .ofSeconds (3 ));
107
- Thread .sleep (Duration .ofSeconds (3 ));
102
+ try (var executor = Executors .newVirtualThreadPerTaskExecutor ()) {
103
+ for (Runnable parker : parkers ) {
104
+ // execute parking task in virtual thread
105
+ var threadRef = new AtomicReference <Thread >();
106
+ executor .submit (() -> {
107
+ threadRef .set (Thread .currentThread ());
108
+ synchronized (lock ) {
109
+ parker .run (); // should pin carrier
110
+ }
111
+ });
112
+
113
+ // wait for the task to start and the virtual thread to park
114
+ Thread thread ;
115
+ while ((thread = threadRef .get ()) == null ) {
116
+ Thread .sleep (10 );
108
117
}
109
- return null ;
110
- });
118
+ try {
119
+ Thread .State state = thread .getState ();
120
+ while (state != Thread .State .WAITING && state != Thread .State .TIMED_WAITING ) {
121
+ Thread .sleep (10 );
122
+ state = thread .getState ();
123
+ }
124
+ } finally {
125
+ LockSupport .unpark (thread );
126
+ }
127
+ }
111
128
} finally {
112
129
recording .stop ();
113
130
}
114
131
115
132
Map <String , Integer > events = sumEvents (recording );
116
- System .out .println (events );
133
+ System .err .println (events );
117
134
118
- // should have two pinned events recorded
135
+ // should have a pinned event for each park
119
136
int pinnedCount = events .getOrDefault ("jdk.VirtualThreadPinned" , 0 );
120
- assertTrue ( pinnedCount == 2 );
137
+ assertEquals ( parkers . length , pinnedCount );
121
138
}
122
139
}
123
140
@@ -164,10 +181,10 @@ void testVirtualThreadSubmitFailed() throws Exception {
164
181
}
165
182
166
183
Map <String , Integer > events = sumEvents (recording );
167
- System .out .println (events );
184
+ System .err .println (events );
168
185
169
186
int count = events .getOrDefault ("jdk.VirtualThreadSubmitFailed" , 0 );
170
- assertTrue ( count == 2 );
187
+ assertEquals ( 2 , count );
171
188
}
172
189
}
173
190
0 commit comments