or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotation-processing.mdaot-optimization.mdcore-infrastructure.mdenvironment-config.mdindex.mdresource-management.mdtask-execution.mdtype-conversion.mdutilities.md

task-execution.mddocs/

0

# Task Execution

1

2

Spring Core provides a comprehensive task execution framework that abstracts thread management and provides both synchronous and asynchronous task execution capabilities. This system supports everything from simple thread pools to modern virtual thread implementations.

3

4

## Core Task Executor Interfaces

5

6

The task execution system is built around a hierarchy of interfaces that provide increasingly sophisticated execution capabilities.

7

8

**TaskExecutor Interface**

9

```java { .api }

10

@FunctionalInterface

11

public interface TaskExecutor extends Executor {

12

void execute(Runnable task);

13

}

14

15

public interface AsyncTaskExecutor extends TaskExecutor {

16

long TIMEOUT_UNLIMITED = Long.MAX_VALUE;

17

long TIMEOUT_IMMEDIATE = 0;

18

19

void execute(Runnable task, long startTimeout);

20

Future<?> submit(Runnable task);

21

<T> Future<T> submit(Callable<T> task);

22

}

23

24

public interface SchedulingTaskExecutor extends AsyncTaskExecutor {

25

boolean prefersShortLivedTasks();

26

}

27

```

28

29

**Task Decorator Interface**

30

```java { .api }

31

@FunctionalInterface

32

public interface TaskDecorator {

33

Runnable decorate(Runnable runnable);

34

}

35

```

36

37

**Usage Examples**

38

```java

39

// Basic task execution

40

TaskExecutor executor = new SimpleAsyncTaskExecutor();

41

42

// Execute fire-and-forget tasks

43

executor.execute(() -> {

44

System.out.println("Task executed in: " + Thread.currentThread().getName());

45

});

46

47

// Asynchronous execution with results

48

AsyncTaskExecutor asyncExecutor = new SimpleAsyncTaskExecutor();

49

50

// Submit runnable task

51

Future<?> future1 = asyncExecutor.submit(() -> {

52

// Long running task

53

processLargeDataset();

54

});

55

56

// Submit callable task

57

Future<String> future2 = asyncExecutor.submit(() -> {

58

return fetchDataFromRemoteService();

59

});

60

61

// Wait for results

62

try {

63

future1.get(5, TimeUnit.SECONDS);

64

String result = future2.get(10, TimeUnit.SECONDS);

65

} catch (TimeoutException ex) {

66

// Handle timeout

67

}

68

69

// Task decoration

70

TaskDecorator decorator = task -> {

71

return () -> {

72

String originalName = Thread.currentThread().getName();

73

Thread.currentThread().setName("CustomTask-" + originalName);

74

try {

75

task.run();

76

} finally {

77

Thread.currentThread().setName(originalName);

78

}

79

};

80

};

81

82

// Apply decorator to executor (implementation-dependent)

83

```

84

85

## Task Executor Implementations

86

87

Spring provides several built-in task executor implementations for different use cases.

88

89

**SimpleAsyncTaskExecutor**

90

```java { .api }

91

public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator

92

implements AsyncTaskExecutor, Serializable {

93

94

public static final int UNBOUNDED_CONCURRENCY = -1;

95

public static final int NO_CONCURRENCY = 0;

96

97

public SimpleAsyncTaskExecutor();

98

public SimpleAsyncTaskExecutor(String threadNamePrefix);

99

public SimpleAsyncTaskExecutor(ThreadFactory threadFactory);

100

101

public void setConcurrencyLimit(int concurrencyLimit);

102

public int getConcurrencyLimit();

103

public boolean isThrottleActive();

104

105

public void setTaskDecorator(TaskDecorator taskDecorator);

106

107

@Override

108

public void execute(Runnable task);

109

@Override

110

public void execute(Runnable task, long startTimeout);

111

@Override

112

public Future<?> submit(Runnable task);

113

@Override

114

public <T> Future<T> submit(Callable<T> task);

115

116

protected void doExecute(Runnable task);

117

protected Thread createThread(Runnable runnable);

118

}

119

```

120

121

**SyncTaskExecutor**

122

```java { .api }

123

public class SyncTaskExecutor implements TaskExecutor, Serializable {

124

@Override

125

public void execute(Runnable task);

126

}

127

```

128

129

**VirtualThreadTaskExecutor (Java 21+)**

130

```java { .api }

131

public class VirtualThreadTaskExecutor implements AsyncTaskExecutor, Serializable {

132

public VirtualThreadTaskExecutor();

133

public VirtualThreadTaskExecutor(String threadNamePrefix);

134

135

public void setThreadNamePrefix(String threadNamePrefix);

136

public String getThreadNamePrefix();

137

138

public void setTaskDecorator(TaskDecorator taskDecorator);

139

public TaskDecorator getTaskDecorator();

140

141

@Override

142

public void execute(Runnable task);

143

@Override

144

public Future<?> submit(Runnable task);

145

@Override

146

public <T> Future<T> submit(Callable<T> task);

147

148

@Override

149

public void execute(Runnable task, long startTimeout);

150

151

protected Thread createVirtualThread(Runnable runnable);

152

}

153

```

154

155

**Usage Examples**

156

```java

157

// Simple async task executor with concurrency control

158

SimpleAsyncTaskExecutor simpleExecutor = new SimpleAsyncTaskExecutor("MyApp-");

159

simpleExecutor.setConcurrencyLimit(10); // Limit to 10 concurrent threads

160

simpleExecutor.setTaskDecorator(task -> {

161

return () -> {

162

long start = System.currentTimeMillis();

163

try {

164

task.run();

165

} finally {

166

long duration = System.currentTimeMillis() - start;

167

System.out.println("Task completed in " + duration + "ms");

168

}

169

};

170

});

171

172

// Execute multiple tasks

173

for (int i = 0; i < 20; i++) {

174

final int taskId = i;

175

simpleExecutor.execute(() -> {

176

System.out.println("Executing task " + taskId +

177

" in thread " + Thread.currentThread().getName());

178

// Simulate work

179

try { Thread.sleep(1000); } catch (InterruptedException e) {}

180

});

181

}

182

183

// Synchronous executor (for testing or single-threaded contexts)

184

TaskExecutor syncExecutor = new SyncTaskExecutor();

185

syncExecutor.execute(() -> {

186

// This will execute in the calling thread

187

System.out.println("Sync execution in: " + Thread.currentThread().getName());

188

});

189

190

// Virtual thread executor (Java 21+)

191

VirtualThreadTaskExecutor virtualExecutor = new VirtualThreadTaskExecutor("VirtualTask-");

192

virtualExecutor.setTaskDecorator(task -> () -> {

193

System.out.println("Virtual thread: " + Thread.currentThread());

194

task.run();

195

});

196

197

// Virtual threads are ideal for I/O-bound tasks

198

List<Future<String>> futures = new ArrayList<>();

199

for (int i = 0; i < 10000; i++) { // Can handle thousands of virtual threads

200

Future<String> future = virtualExecutor.submit(() -> {

201

// Simulate I/O operation

202

Thread.sleep(Duration.ofSeconds(1));

203

return "Result from virtual thread";

204

});

205

futures.add(future);

206

}

207

208

// Collect results

209

List<String> results = futures.stream()

210

.map(future -> {

211

try { return future.get(); }

212

catch (Exception e) { return "Error"; }

213

})

214

.collect(Collectors.toList());

215

```

216

217

## Thread Pool Task Executor Support

218

219

While the core module doesn't include full thread pool implementations, it provides the foundation interfaces that are used by Spring's thread pool executors in other modules.

220

221

**Lifecycle Management**

222

```java { .api }

223

public interface DisposableBean {

224

void destroy() throws Exception;

225

}

226

227

public interface InitializingBean {

228

void afterPropertiesSet() throws Exception;

229

}

230

231

// Task executors often implement these for proper lifecycle management

232

public interface TaskExecutorConfiguration {

233

void initialize();

234

void shutdown();

235

boolean awaitTermination(long timeout, TimeUnit unit);

236

}

237

```

238

239

**Usage Examples**

240

```java

241

// Custom task executor with lifecycle management

242

public class ManagedTaskExecutor implements AsyncTaskExecutor, InitializingBean, DisposableBean {

243

private ExecutorService executor;

244

private final String threadNamePrefix;

245

private TaskDecorator taskDecorator;

246

247

public ManagedTaskExecutor(String threadNamePrefix) {

248

this.threadNamePrefix = threadNamePrefix;

249

}

250

251

@Override

252

public void afterPropertiesSet() {

253

ThreadFactory threadFactory = new CustomizableThreadFactory(threadNamePrefix);

254

this.executor = Executors.newCachedThreadPool(threadFactory);

255

}

256

257

@Override

258

public void destroy() throws Exception {

259

if (executor != null) {

260

executor.shutdown();

261

if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {

262

executor.shutdownNow();

263

}

264

}

265

}

266

267

@Override

268

public void execute(Runnable task) {

269

Runnable decoratedTask = (taskDecorator != null) ? taskDecorator.decorate(task) : task;

270

executor.execute(decoratedTask);

271

}

272

273

@Override

274

public Future<?> submit(Runnable task) {

275

Runnable decoratedTask = (taskDecorator != null) ? taskDecorator.decorate(task) : task;

276

return executor.submit(decoratedTask);

277

}

278

279

@Override

280

public <T> Future<T> submit(Callable<T> task) {

281

return executor.submit(task);

282

}

283

284

public void setTaskDecorator(TaskDecorator taskDecorator) {

285

this.taskDecorator = taskDecorator;

286

}

287

}

288

289

// Usage with Spring lifecycle

290

ManagedTaskExecutor managedExecutor = new ManagedTaskExecutor("Managed-");

291

managedExecutor.setTaskDecorator(task -> {

292

return () -> {

293

MDC.put("taskId", UUID.randomUUID().toString());

294

try {

295

task.run();

296

} finally {

297

MDC.clear();

298

}

299

};

300

});

301

302

managedExecutor.afterPropertiesSet(); // Initialize

303

304

// Use the executor

305

Future<String> result = managedExecutor.submit(() -> {

306

// Task execution with proper logging context

307

return "Task completed";

308

});

309

310

// Cleanup

311

managedExecutor.destroy();

312

```

313

314

## Task Execution Utilities

315

316

**CustomizableThreadCreator**

317

```java { .api }

318

public class CustomizableThreadCreator implements Serializable {

319

public static final String DEFAULT_THREAD_NAME_PREFIX =

320

ClassUtils.getShortName(CustomizableThreadCreator.class) + "-";

321

322

private String threadNamePrefix = DEFAULT_THREAD_NAME_PREFIX;

323

private int threadPriority = Thread.NORM_PRIORITY;

324

private boolean daemon = false;

325

private ThreadGroup threadGroup;

326

private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;

327

328

public CustomizableThreadCreator();

329

public CustomizableThreadCreator(String threadNamePrefix);

330

331

public void setThreadNamePrefix(String threadNamePrefix);

332

public String getThreadNamePrefix();

333

334

public void setThreadPriority(int threadPriority);

335

public int getThreadPriority();

336

337

public void setDaemon(boolean daemon);

338

public boolean isDaemon();

339

340

public void setThreadGroupName(String name);

341

public void setThreadGroup(ThreadGroup threadGroup);

342

public ThreadGroup getThreadGroup();

343

344

public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler);

345

public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler();

346

347

public Thread createThread(Runnable runnable);

348

protected String nextThreadName();

349

public String getDefaultThreadNamePrefix();

350

}

351

```

352

353

**Usage Examples**

354

```java

355

// Customizable thread creation

356

CustomizableThreadCreator threadCreator = new CustomizableThreadCreator("WorkerPool-");

357

threadCreator.setThreadPriority(Thread.MAX_PRIORITY);

358

threadCreator.setDaemon(true);

359

threadCreator.setUncaughtExceptionHandler((thread, ex) -> {

360

System.err.println("Uncaught exception in thread " + thread.getName() + ": " + ex);

361

});

362

363

// Create custom threads

364

Thread workerThread = threadCreator.createThread(() -> {

365

// Worker task implementation

366

performWork();

367

});

368

369

workerThread.start();

370

371

// Use with task executors

372

public class CustomThreadTaskExecutor extends SimpleAsyncTaskExecutor {

373

public CustomThreadTaskExecutor() {

374

super("CustomTask-");

375

setThreadPriority(Thread.HIGH_PRIORITY);

376

setDaemon(false);

377

}

378

379

@Override

380

protected Thread createThread(Runnable runnable) {

381

Thread thread = super.createThread(runnable);

382

thread.setUncaughtExceptionHandler((t, e) -> {

383

// Custom exception handling

384

handleTaskException(t, e);

385

});

386

return thread;

387

}

388

389

private void handleTaskException(Thread thread, Throwable exception) {

390

// Log exception, notify monitoring system, etc.

391

}

392

}

393

```

394

395

## Asynchronous Method Support Foundation

396

397

While async method execution is handled in Spring Context, the core module provides the foundational interfaces.

398

399

**Future Result Handling**

400

```java { .api }

401

// Standard JDK interfaces that task executors work with

402

public interface Future<V> {

403

boolean cancel(boolean mayInterruptIfRunning);

404

boolean isCancelled();

405

boolean isDone();

406

V get() throws InterruptedException, ExecutionException;

407

V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;

408

}

409

410

public interface Callable<V> {

411

V call() throws Exception;

412

}

413

414

// Spring's ListenableFuture (from spring-context) extends this foundation

415

```

416

417

**Usage Examples**

418

```java

419

// Working with Future results

420

AsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();

421

422

// Submit tasks and handle results

423

Future<Integer> calculation = executor.submit(() -> {

424

// Expensive calculation

425

Thread.sleep(2000);

426

return 42;

427

});

428

429

Future<String> dataFetch = executor.submit(() -> {

430

// Data fetching operation

431

return fetchFromDatabase();

432

});

433

434

// Non-blocking check

435

if (calculation.isDone()) {

436

try {

437

Integer result = calculation.get();

438

System.out.println("Calculation result: " + result);

439

} catch (ExecutionException ex) {

440

System.err.println("Calculation failed: " + ex.getCause());

441

}

442

}

443

444

// Blocking wait with timeout

445

try {

446

String data = dataFetch.get(5, TimeUnit.SECONDS);

447

processData(data);

448

} catch (TimeoutException ex) {

449

System.err.println("Data fetch timed out");

450

dataFetch.cancel(true);

451

} catch (ExecutionException ex) {

452

System.err.println("Data fetch failed: " + ex.getCause());

453

}

454

455

// Batch processing with CompletableFuture composition

456

List<Future<String>> futures = IntStream.range(0, 10)

457

.mapToObj(i -> executor.submit(() -> processItem(i)))

458

.collect(Collectors.toList());

459

460

// Wait for all to complete

461

List<String> results = futures.stream()

462

.map(future -> {

463

try {

464

return future.get(30, TimeUnit.SECONDS);

465

} catch (Exception ex) {

466

return "Error: " + ex.getMessage();

467

}

468

})

469

.collect(Collectors.toList());

470

```

471

472

## Task Execution Patterns

473

474

**Common Patterns and Best Practices**

475

```java

476

// Pattern 1: Fire-and-forget tasks

477

public class NotificationService {

478

private final TaskExecutor taskExecutor;

479

480

public NotificationService(TaskExecutor taskExecutor) {

481

this.taskExecutor = taskExecutor;

482

}

483

484

public void sendNotification(String message, String recipient) {

485

taskExecutor.execute(() -> {

486

// Send email/SMS notification asynchronously

487

emailService.send(recipient, message);

488

});

489

}

490

}

491

492

// Pattern 2: Producer-consumer with task decoration

493

public class AuditedTaskExecutor implements TaskExecutor {

494

private final TaskExecutor delegate;

495

private final AuditService auditService;

496

497

public AuditedTaskExecutor(TaskExecutor delegate, AuditService auditService) {

498

this.delegate = delegate;

499

this.auditService = auditService;

500

}

501

502

@Override

503

public void execute(Runnable task) {

504

String taskId = UUID.randomUUID().toString();

505

Runnable auditedTask = () -> {

506

auditService.logTaskStart(taskId);

507

long startTime = System.currentTimeMillis();

508

try {

509

task.run();

510

auditService.logTaskSuccess(taskId, System.currentTimeMillis() - startTime);

511

} catch (Exception ex) {

512

auditService.logTaskFailure(taskId, ex);

513

throw ex;

514

}

515

};

516

delegate.execute(auditedTask);

517

}

518

}

519

520

// Pattern 3: Graceful shutdown

521

public class GracefulTaskExecutor implements AsyncTaskExecutor, DisposableBean {

522

private final AsyncTaskExecutor delegate;

523

private final List<Future<?>> activeTasks = Collections.synchronizedList(new ArrayList<>());

524

private volatile boolean shutdownRequested = false;

525

526

public GracefulTaskExecutor(AsyncTaskExecutor delegate) {

527

this.delegate = delegate;

528

}

529

530

@Override

531

public Future<?> submit(Runnable task) {

532

if (shutdownRequested) {

533

throw new IllegalStateException("Executor is shutting down");

534

}

535

536

Future<?> future = delegate.submit(() -> {

537

try {

538

task.run();

539

} finally {

540

activeTasks.removeIf(f -> f.isDone() || f.isCancelled());

541

}

542

});

543

544

activeTasks.add(future);

545

return future;

546

}

547

548

@Override

549

public void destroy() throws Exception {

550

shutdownRequested = true;

551

552

// Wait for active tasks to complete

553

long deadline = System.currentTimeMillis() + 30000; // 30 second timeout

554

while (!activeTasks.isEmpty() && System.currentTimeMillis() < deadline) {

555

Thread.sleep(100);

556

activeTasks.removeIf(f -> f.isDone() || f.isCancelled());

557

}

558

559

// Cancel remaining tasks

560

activeTasks.forEach(future -> future.cancel(true));

561

}

562

}

563

```

564

565

This task execution framework provides the foundation for Spring's asynchronous processing capabilities, enabling developers to build scalable, non-blocking applications with proper resource management and lifecycle control.