0
# Runtime Context and Threading
1
2
The Runtime Context and Threading capability provides execution mode detection, launch mode management, and threading control for optimal performance in Quarkus applications.
3
4
## Launch Mode Management
5
6
### Launch Mode Detection
7
8
```java { .api }
9
public enum LaunchMode {
10
/**
11
* Production mode - optimized for performance.
12
*/
13
NORMAL,
14
15
/**
16
* Development mode - hot reload and dev services enabled.
17
*/
18
DEVELOPMENT,
19
20
/**
21
* Test mode - running in test environment.
22
*/
23
TEST;
24
25
/**
26
* Check if current mode is development or test.
27
* @return true if development or test mode
28
*/
29
public boolean isDevOrTest();
30
31
/**
32
* Get the default configuration profile for this launch mode.
33
* @return Profile name ("prod", "dev", or "test")
34
*/
35
public String getDefaultProfile();
36
37
/**
38
* Get the current launch mode.
39
* @return Current launch mode
40
*/
41
public static LaunchMode current();
42
43
/**
44
* Check if running in development mode.
45
* @return true if development mode
46
*/
47
public static boolean isDev();
48
49
/**
50
* Check if running in remote development mode.
51
* @return true if remote development mode
52
*/
53
public static boolean isRemoteDev();
54
}
55
```
56
57
## Execution Mode Detection
58
59
### Execution Phases
60
61
```java { .api }
62
public enum ExecutionMode {
63
/**
64
* Static initialization phase - executed at build time.
65
*/
66
STATIC_INIT,
67
68
/**
69
* Runtime initialization phase - executed at startup.
70
*/
71
RUNTIME_INIT,
72
73
/**
74
* Application running phase - normal operation.
75
*/
76
RUNNING,
77
78
/**
79
* Uninitialized state.
80
*/
81
UNSET;
82
83
/**
84
* Get the current execution mode.
85
* @return Current execution mode
86
*/
87
public static ExecutionMode current();
88
}
89
```
90
91
## Threading Control
92
93
### Blocking Operation Control
94
95
```java { .api }
96
public final class BlockingOperationControl {
97
/**
98
* Check if blocking operations are allowed on current thread.
99
* @return true if blocking operations are allowed
100
*/
101
public static boolean isBlockingAllowed();
102
103
/**
104
* Configure IO thread detectors.
105
* @param detectors Array of IO thread detectors
106
*/
107
public static void setIoThreadDetector(IOThreadDetector... detectors);
108
}
109
```
110
111
### IO Thread Detection
112
113
```java { .api }
114
public interface IOThreadDetector {
115
/**
116
* Check if the current thread is an IO thread.
117
* IO threads should not perform blocking operations.
118
* @return true if current thread is an IO thread
119
*/
120
boolean isInIOThread();
121
}
122
```
123
124
### Blocking Operation Exception
125
126
```java { .api }
127
public class BlockingOperationNotAllowedException extends IllegalStateException {
128
/**
129
* Create exception for blocking operation attempt on IO thread.
130
* @param message Error message
131
*/
132
public BlockingOperationNotAllowedException(String message);
133
134
/**
135
* Create exception with message and cause.
136
* @param message Error message
137
* @param cause Root cause
138
*/
139
public BlockingOperationNotAllowedException(String message, Throwable cause);
140
}
141
```
142
143
## Usage Examples
144
145
### Launch Mode Detection
146
147
```java
148
import io.quarkus.runtime.LaunchMode;
149
import jakarta.enterprise.context.ApplicationScoped;
150
151
@ApplicationScoped
152
public class EnvironmentService {
153
154
public void configureEnvironment() {
155
LaunchMode mode = LaunchMode.current();
156
157
switch (mode) {
158
case DEVELOPMENT:
159
configureDevelopmentMode();
160
break;
161
case TEST:
162
configureTestMode();
163
break;
164
case NORMAL:
165
configureProductionMode();
166
break;
167
}
168
169
// Check if dev or test
170
if (mode.isDevOrTest()) {
171
enableDebugLogging();
172
}
173
174
// Get associated profile
175
String profile = mode.getDefaultProfile();
176
System.out.println("Running with profile: " + profile);
177
}
178
179
private void configureDevelopmentMode() {
180
System.out.println("Development mode: Hot reload enabled");
181
// Enable dev services, hot reload, etc.
182
}
183
184
private void configureTestMode() {
185
System.out.println("Test mode: Test containers starting");
186
// Configure test environment
187
}
188
189
private void configureProductionMode() {
190
System.out.println("Production mode: Performance optimizations enabled");
191
// Configure for production
192
}
193
194
private void enableDebugLogging() {
195
System.out.println("Debug logging enabled for dev/test mode");
196
}
197
}
198
```
199
200
### Execution Mode Tracking
201
202
```java
203
import io.quarkus.runtime.ExecutionMode;
204
import io.quarkus.runtime.annotations.Recorder;
205
import io.quarkus.runtime.annotations.StaticInit;
206
import io.quarkus.runtime.annotations.RuntimeInit;
207
208
@Recorder
209
public class InitializationRecorder {
210
211
@StaticInit
212
public void staticInitialization() {
213
ExecutionMode mode = ExecutionMode.current();
214
System.out.println("Current execution mode: " + mode);
215
216
if (mode == ExecutionMode.STATIC_INIT) {
217
System.out.println("Performing static initialization");
218
// Build-time initialization logic
219
initializeStaticResources();
220
}
221
}
222
223
@RuntimeInit
224
public void runtimeInitialization() {
225
ExecutionMode mode = ExecutionMode.current();
226
227
if (mode == ExecutionMode.RUNTIME_INIT) {
228
System.out.println("Performing runtime initialization");
229
// Runtime initialization logic
230
initializeRuntimeResources();
231
}
232
}
233
234
public void applicationRunning() {
235
ExecutionMode mode = ExecutionMode.current();
236
237
if (mode == ExecutionMode.RUNNING) {
238
System.out.println("Application is now running");
239
// Normal operation logic
240
}
241
}
242
243
private void initializeStaticResources() {
244
// Static initialization logic
245
}
246
247
private void initializeRuntimeResources() {
248
// Runtime initialization logic
249
}
250
}
251
```
252
253
### IO Thread Detection and Blocking Control
254
255
```java
256
import io.quarkus.runtime.BlockingOperationControl;
257
import io.quarkus.runtime.IOThreadDetector;
258
import io.quarkus.runtime.BlockingOperationNotAllowedException;
259
import jakarta.enterprise.context.ApplicationScoped;
260
261
@ApplicationScoped
262
public class ThreadingService {
263
264
public void performPotentiallyBlockingOperation() {
265
// Check if blocking operations are allowed
266
if (!BlockingOperationControl.isBlockingAllowed()) {
267
throw new BlockingOperationNotAllowedException(
268
"Blocking operation attempted on IO thread"
269
);
270
}
271
272
// Safe to perform blocking operation
273
performBlockingIO();
274
}
275
276
public void safeBlockingOperation() {
277
try {
278
// This will automatically check and throw if on IO thread
279
performBlockingIO();
280
} catch (BlockingOperationNotAllowedException e) {
281
// Handle the case where we're on an IO thread
282
System.err.println("Cannot perform blocking operation: " + e.getMessage());
283
284
// Alternative: schedule on blocking thread pool
285
scheduleOnBlockingThread(this::performBlockingIO);
286
}
287
}
288
289
private void performBlockingIO() {
290
try {
291
// Simulated blocking operation
292
Thread.sleep(1000);
293
System.out.println("Blocking operation completed");
294
} catch (InterruptedException e) {
295
Thread.currentThread().interrupt();
296
}
297
}
298
299
private void scheduleOnBlockingThread(Runnable task) {
300
// Schedule task on blocking thread pool
301
// Implementation depends on your threading model
302
CompletableFuture.runAsync(task);
303
}
304
}
305
```
306
307
### Custom IO Thread Detector
308
309
```java
310
import io.quarkus.runtime.IOThreadDetector;
311
import io.quarkus.runtime.BlockingOperationControl;
312
313
public class CustomIOThreadDetector implements IOThreadDetector {
314
315
@Override
316
public boolean isInIOThread() {
317
Thread currentThread = Thread.currentThread();
318
String threadName = currentThread.getName();
319
320
// Detect Vert.x event loop threads
321
if (threadName.contains("vert.x-eventloop")) {
322
return true;
323
}
324
325
// Detect Netty IO threads
326
if (threadName.contains("netty-io")) {
327
return true;
328
}
329
330
// Add other IO thread detection logic
331
return false;
332
}
333
}
334
335
// Register the custom detector
336
public class ThreadDetectionSetup {
337
338
public void setupDetectors() {
339
IOThreadDetector customDetector = new CustomIOThreadDetector();
340
BlockingOperationControl.setIoThreadDetector(customDetector);
341
}
342
}
343
```
344
345
### Conditional Logic Based on Context
346
347
```java
348
import io.quarkus.runtime.LaunchMode;
349
import io.quarkus.runtime.ExecutionMode;
350
import jakarta.enterprise.context.ApplicationScoped;
351
import jakarta.annotation.PostConstruct;
352
353
@ApplicationScoped
354
public class ContextAwareService {
355
356
@PostConstruct
357
public void initialize() {
358
LaunchMode launchMode = LaunchMode.current();
359
ExecutionMode executionMode = ExecutionMode.current();
360
361
System.out.println("Launch Mode: " + launchMode);
362
System.out.println("Execution Mode: " + executionMode);
363
364
// Configure based on context
365
configureForContext(launchMode, executionMode);
366
}
367
368
private void configureForContext(LaunchMode launchMode, ExecutionMode executionMode) {
369
// Development-specific configuration
370
if (launchMode == LaunchMode.DEVELOPMENT) {
371
if (executionMode == ExecutionMode.RUNTIME_INIT) {
372
setupDevelopmentTools();
373
}
374
enableHotReload();
375
}
376
377
// Test-specific configuration
378
if (launchMode == LaunchMode.TEST) {
379
setupTestEnvironment();
380
}
381
382
// Production optimizations
383
if (launchMode == LaunchMode.NORMAL) {
384
enableProductionOptimizations();
385
}
386
387
// Runtime vs static initialization
388
switch (executionMode) {
389
case STATIC_INIT:
390
performStaticSetup();
391
break;
392
case RUNTIME_INIT:
393
performRuntimeSetup();
394
break;
395
case RUNNING:
396
startNormalOperation();
397
break;
398
case UNSET:
399
System.out.println("Execution mode not yet determined");
400
break;
401
}
402
}
403
404
private void setupDevelopmentTools() {
405
System.out.println("Setting up development tools");
406
}
407
408
private void enableHotReload() {
409
System.out.println("Hot reload enabled");
410
}
411
412
private void setupTestEnvironment() {
413
System.out.println("Setting up test environment");
414
}
415
416
private void enableProductionOptimizations() {
417
System.out.println("Production optimizations enabled");
418
}
419
420
private void performStaticSetup() {
421
System.out.println("Performing static setup");
422
}
423
424
private void performRuntimeSetup() {
425
System.out.println("Performing runtime setup");
426
}
427
428
private void startNormalOperation() {
429
System.out.println("Starting normal operation");
430
}
431
}
432
```
433
434
### Thread-Safe Operations
435
436
```java
437
import io.quarkus.runtime.BlockingOperationControl;
438
import java.util.concurrent.CompletableFuture;
439
import java.util.concurrent.Executor;
440
441
public class ThreadSafeOperations {
442
443
private final Executor blockingExecutor;
444
445
public ThreadSafeOperations(Executor blockingExecutor) {
446
this.blockingExecutor = blockingExecutor;
447
}
448
449
public CompletableFuture<String> performAsyncOperation() {
450
if (BlockingOperationControl.isBlockingAllowed()) {
451
// We're on a blocking thread, safe to do blocking operations
452
return CompletableFuture.completedFuture(performSynchronousOperation());
453
} else {
454
// We're on an IO thread, delegate to blocking executor
455
return CompletableFuture.supplyAsync(
456
this::performSynchronousOperation,
457
blockingExecutor
458
);
459
}
460
}
461
462
private String performSynchronousOperation() {
463
// This method performs blocking operations
464
try {
465
Thread.sleep(100); // Simulated blocking operation
466
return "Operation completed";
467
} catch (InterruptedException e) {
468
Thread.currentThread().interrupt();
469
return "Operation interrupted";
470
}
471
}
472
473
public void smartBlocking() {
474
if (BlockingOperationControl.isBlockingAllowed()) {
475
// Direct execution on current thread
476
System.out.println("Executing on blocking thread");
477
performSynchronousOperation();
478
} else {
479
// Schedule on blocking thread and wait
480
System.out.println("Scheduling on blocking thread from IO thread");
481
CompletableFuture<String> future = CompletableFuture.supplyAsync(
482
this::performSynchronousOperation,
483
blockingExecutor
484
);
485
486
// Note: This join() could still block the IO thread
487
// In practice, you'd want to return the CompletableFuture
488
// or use reactive patterns
489
String result = future.join();
490
System.out.println("Result: " + result);
491
}
492
}
493
}
494
```
495
496
## Best Practices
497
498
### Thread Safety
499
500
1. **Always check** `BlockingOperationControl.isBlockingAllowed()` before blocking operations
501
2. **Use CompletableFuture** or reactive patterns when on IO threads
502
3. **Configure custom IO thread detectors** for specific threading models
503
4. **Handle BlockingOperationNotAllowedException** gracefully
504
505
### Context Awareness
506
507
1. **Use LaunchMode** to conditionally enable development features
508
2. **Use ExecutionMode** to determine initialization phase
509
3. **Configure differently** for dev/test vs production environments
510
4. **Leverage profiles** associated with launch modes
511
512
### Performance Optimization
513
514
1. **Avoid blocking operations** on IO threads
515
2. **Use appropriate thread pools** for different operation types
516
3. **Configure thread detectors** to match your application's threading model
517
4. **Monitor thread usage** in production environments