- Usage: A thread-safe variant of
HashMap
. - Example:
ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>(); map.put("key", 1); int value = map.get("key");
- Usage: A thread-safe variant of ArrayList for read-mostly scenarios.
- Example:
List<String> list = new CopyOnWriteArrayList<>();
list.add("element");
for (String s : list) {
System.out.println(s);
}
- Usage: Thread-safe queues that block on operations when necessary.
Types: ArrayBlockingQueue LinkedBlockingQueue PriorityBlockingQueue
- Example:
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
queue.put("element");
String element = queue.take();
Usage: A thread-safe variant of TreeMap for scalable sorted maps.
- Example:
ConcurrentNavigableMap<String, Integer> map = new ConcurrentSkipListMap<>();
map.put("key", 1);
int value = map.get("key");
Usage: A thread-safe queue that holds elements until a delay has expired.
- Example:
DelayQueue<DelayedElement> queue = new DelayQueue<>();
queue.put(new DelayedElement());
DelayedElement element = queue.take();
Creating an ExecutorService
Fixed Thread Pool:
ExecutorService executor = Executors.newFixedThreadPool(5);
Single Thread Executor:
ExecutorService executor = Executors.newSingleThreadExecutor();
Cached Thread Pool:
ExecutorService executor = Executors.newCachedThreadPool();
Scheduled Thread Pool:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Submitting Tasks
Runnable Task:
executor.submit(() -> {
System.out.println("Task executed");
});
Callable Task:
Future<String> future = executor.submit(() -> {
return "Task result";
});
Shutting Down ExecutorService Shutdown gracefully:
executor.shutdown();
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
Force shutdown:
executor.shutdownNow();
-
Use Appropriate Data Structures Choose thread-safe data structures from the java.util.concurrent package. Example: Use ConcurrentHashMap instead of HashMap.
-
Minimize Locking Prefer using higher-level concurrency utilities like Semaphore, CountDownLatch, CyclicBarrier over explicit locks. Example:
Semaphore semaphore = new Semaphore(1);
semaphore.acquire();
try {
// critical section
} finally {
semaphore.release();
}
- Use Executors for Thread Management Avoid manual thread creation; use ExecutorService for better management. Example:
ExecutorService executor = Executors.newFixedThreadPool(5);
executor.submit(() -> {
// task
});
executor.shutdown();
- Handle Exceptions in Tasks Ensure that tasks submitted to an executor service handle exceptions properly. Example:
executor.submit(() -> {
try {
// task
} catch (Exception e) {
e.printStackTrace();
}
});
- Properly Shutdown ExecutorService Always shutdown ExecutorService to release resources. Example:
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
- Avoid Blocking Operations in Tasks Avoid long-running or blocking operations inside tasks to keep the thread pool responsive. Example:
executor.submit(() -> {
// Avoid blocking calls like Thread.sleep() or I/O operations
});
- Use Thread-Safe Collections Use collections from java.util.concurrent for thread safety. Example:
ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();