← Back to Home

Sprint Challenge: Concurrency in Java

Challenge Overview

This sprint challenge tests your understanding of multi-threading, thread safety, and executor services in Java. You'll demonstrate your ability to create and manage threads, implement thread-safe code, and use executor services for efficient task execution.

View Challenge on GitHub

Learning Objectives Assessed

Creating and Managing Threads

You'll be expected to demonstrate your ability to create threads using both the Thread class and Runnable interface, manage thread lifecycles, and understand thread states.

// Creating a thread using Runnable interface
Runnable task = () -> {
    System.out.println("Task running in thread: " + Thread.currentThread().getName());
};

Thread thread = new Thread(task);
thread.start();  // Start the thread

// Wait for the thread to complete
try {
    thread.join();
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

Thread Safety and Synchronization

You'll need to identify race conditions in shared data structures and implement appropriate synchronization mechanisms to ensure thread safety.

// Thread-safe implementation using synchronized methods
public class ThreadSafeCounter {
    private int count = 0;
    
    public synchronized void increment() {
        count++;
    }
    
    public synchronized int getCount() {
        return count;
    }
}

Using ExecutorService

You'll be expected to configure and use ExecutorService for efficient thread pool management, task submission, and proper shutdown.

// Using ExecutorService to manage a thread pool
ExecutorService executor = Executors.newFixedThreadPool(4);

// Submit multiple tasks
for (int i = 0; i < 10; i++) {
    final int taskId = i;
    executor.submit(() -> {
        System.out.println("Task " + taskId + " executing on " + 
                          Thread.currentThread().getName());
    });
}

// Shutdown the executor cleanly
executor.shutdown();
try {
    if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
        executor.shutdownNow();
    }
} catch (InterruptedException e) {
    executor.shutdownNow();
    Thread.currentThread().interrupt();
}

Working with Future Objects

You'll need to use Future objects to retrieve results from asynchronous tasks, handle exceptions, and implement timeout mechanisms.

// Working with Future objects for asynchronous results
ExecutorService executor = Executors.newCachedThreadPool();

Callable<Integer> task = () -> {
    // Simulate complex calculation
    Thread.sleep(1000);
    return 42;
};

Future<Integer> future = executor.submit(task);

try {
    // Get the result with a timeout
    Integer result = future.get(2, TimeUnit.SECONDS);
    System.out.println("Task result: " + result);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
    // Handle exceptions appropriately
}

Submission Guidelines

To complete this sprint challenge:

  1. Fork the repository to your GitHub account
  2. Clone your forked repository to your local machine
  3. Complete all required tasks and pass all tests
  4. Push your changes to your forked repository
  5. Submit the link to your repository in the learning platform

You have three hours to complete this challenge. Focus on functionality and code quality.