Java Collections synchronizedSortedSet() Method

The synchronizedSortedSet() method in Java is a utility method provided by the java.util.Collections class. It returns a synchronized (thread-safe) sorted set backed by the specified sorted set. This method is particularly useful when you need to ensure that a sorted set is thread-safe in a concurrent environment.

Table of Contents

  1. Introduction
  2. synchronizedSortedSet() Method Syntax
  3. Examples
    • Basic Usage of synchronizedSortedSet()
    • Using synchronizedSortedSet() with Custom Classes
  4. Real-World Use Case
  5. Conclusion

Introduction

The Collections.synchronizedSortedSet() method provides a way to wrap a given sorted set with synchronized access, ensuring that only one thread can access the set at a time. This is crucial in concurrent applications where multiple threads might try to modify the set simultaneously, leading to race conditions or inconsistent data.

The returned sorted set is a synchronized view of the specified set, meaning that all operations on the set are synchronized using the set’s intrinsic lock. This includes operations such as adding, removing, or iterating over the elements, as well as sorted set-specific operations like accessing subsets.

synchronizedSortedSet() Method Syntax

The syntax for the synchronizedSortedSet() method is as follows:

public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)

Parameters:

  • s: The sorted set to be wrapped in a synchronized view.

Returns:

  • A synchronized (thread-safe) sorted set backed by the specified sorted set.

Throws:

  • NullPointerException if the specified sorted set is null.

Examples

Basic Usage of synchronizedSortedSet()

The following example demonstrates how to use the synchronizedSortedSet() method to create a synchronized view of a sorted set.

Example

import java.util.Collections;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

public class SynchronizedSortedSetExample {
    public static void main(String[] args) {
        // Create a regular TreeSet
        SortedSet<String> sortedSet = new TreeSet<>();
        sortedSet.add("Apple");
        sortedSet.add("Banana");
        sortedSet.add("Cherry");

        // Create a synchronized (thread-safe) sorted set backed by the TreeSet
        SortedSet<String> synchronizedSortedSet = Collections.synchronizedSortedSet(sortedSet);

        // Display the synchronized sorted set
        System.out.println("Synchronized Sorted Set: " + synchronizedSortedSet);

        // Use synchronized block for iteration to ensure thread safety
        synchronized (synchronizedSortedSet) {
            Iterator<String> iterator = synchronizedSortedSet.iterator();
            while (iterator.hasNext()) {
                System.out.println("Element: " + iterator.next());
            }
        }

        // Adding and removing elements in a synchronized sorted set
        synchronized (synchronizedSortedSet) {
            synchronizedSortedSet.add("Date");
            synchronizedSortedSet.remove("Apple");
        }

        // Display the modified synchronized sorted set
        System.out.println("Modified Synchronized Sorted Set: " + synchronizedSortedSet);
    }
}

Output:

Synchronized Sorted Set: [Apple, Banana, Cherry]
Element: Apple
Element: Banana
Element: Cherry
Modified Synchronized Sorted Set: [Banana, Cherry, Date]

Using synchronizedSortedSet() with Custom Classes

You can also use the synchronizedSortedSet() method with sorted sets containing instances of custom classes.

Example

import java.util.Collections;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

class Student implements Comparable<Student> {
    String name;
    int id;

    Student(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public int compareTo(Student other) {
        return Integer.compare(this.id, other.id);
    }

    @Override
    public String toString() {
        return name + " (ID: " + id + ")";
    }
}

public class CustomSynchronizedSortedSetExample {
    public static void main(String[] args) {
        // Create a sorted set of students
        SortedSet<Student> students = new TreeSet<>();
        students.add(new Student("Amit", 101));
        students.add(new Student("Neha", 102));
        students.add(new Student("Raj", 103));

        // Create a synchronized (thread-safe) sorted set backed by the student set
        SortedSet<Student> synchronizedStudents = Collections.synchronizedSortedSet(students);

        // Display the synchronized student sorted set
        System.out.println("Synchronized Student Sorted Set: " + synchronizedStudents);

        // Use synchronized block for iteration to ensure thread safety
        synchronized (synchronizedStudents) {
            Iterator<Student> iterator = synchronizedStudents.iterator();
            while (iterator.hasNext()) {
                System.out.println("Student: " + iterator.next());
            }
        }

        // Modifying the synchronized sorted set
        synchronized (synchronizedStudents) {
            synchronizedStudents.add(new Student("Vikram", 104));
            synchronizedStudents.remove(new Student("Neha", 102));
        }

        // Display the modified synchronized student sorted set
        System.out.println("Modified Synchronized Student Sorted Set: " + synchronizedStudents);
    }
}

Output:

Synchronized Student Sorted Set: [Amit (ID: 101), Neha (ID: 102), Raj (ID: 103)]
Student: Amit (ID: 101)
Student: Neha (ID: 102)
Student: Raj (ID: 103)
Modified Synchronized Student Sorted Set: [Amit (ID: 101), Raj (ID: 103), Vikram (ID: 104)]

Explanation:

  1. Synchronized View: The synchronizedSortedSet() method returns a synchronized view of the specified sorted set, ensuring thread-safe access.
  2. Synchronized Block: When iterating over the synchronized sorted set, a synchronized block is used to avoid concurrent modification exceptions and ensure thread safety.
  3. Custom Class: The method works with custom class instances, allowing you to create synchronized sorted sets with user-defined objects.

Real-World Use Case

Thread-Safe Access to a Shared Resource

In real-world applications, the synchronizedSortedSet() method can be used to manage thread-safe access to shared resources, such as a set of sorted tasks in a multi-threaded environment.

Example

Imagine a scenario where you need to manage a shared set of sorted tasks in a concurrent application.

import java.util.Collections;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

class Task implements Comparable<Task> {
    String description;
    int priority;

    Task(String description, int priority) {
        this.description = description;
        this.priority = priority;
    }

    @Override
    public int compareTo(Task other) {
        return Integer.compare(this.priority, other.priority);
    }

    @Override
    public String toString() {
        return description + " (Priority: " + priority + ")";
    }
}

public class TaskManager {
    private final SortedSet<Task> tasks;

    public TaskManager() {
        // Initialize the task set and wrap it in a synchronized view
        this.tasks = Collections.synchronizedSortedSet(new TreeSet<>());
    }

    public void addTask(Task task) {
        synchronized (tasks) {
            tasks.add(task);
        }
    }

    public void removeTask(Task task) {
        synchronized (tasks) {
            tasks.remove(task);
        }
    }

    public void displayTasks() {
        // Use synchronized block for iteration to ensure thread safety
        synchronized (tasks) {
            Iterator<Task> iterator = tasks.iterator();
            while (iterator.hasNext()) {
                System.out.println("Task: " + iterator.next());
            }
        }
    }

    public static void main(String[] args) {
        TaskManager taskManager = new TaskManager();

        // Add tasks to the manager
        taskManager.addTask(new Task("Review code", 2));
        taskManager.addTask(new Task("Write tests", 1));
        taskManager.addTask(new Task("Deploy application", 3));

        // Display all tasks
        System.out.println("Task List:");
        taskManager.displayTasks();

        // Remove a task
        taskManager.removeTask(new Task("Write tests", 1));

        // Display remaining tasks
        System.out.println("\nUpdated Task List:");
        taskManager.displayTasks();
    }
}

Output:

Task List:
Task: Write tests (Priority: 1)
Task: Review code (Priority: 2)
Task: Deploy application (Priority: 3)

Updated Task List:
Task: Review code (Priority: 2)
Task: Deploy application (Priority: 3)

Explanation:

  1. Task Manager: The TaskManager class manages a sorted set of tasks, ensuring thread-safe access by wrapping the set in a synchronized view.
  2. Concurrent Environment: The synchronizedSortedSet() method is used to synchronize access to the shared set, preventing race conditions and ensuring data consistency.
  3. Task Management: The example demonstrates the use of a sorted set to manage tasks based on their priority.

Conclusion

The Collections.synchronizedSortedSet() method is a powerful utility for creating synchronized (thread-safe) sorted sets in Java. By providing a simple way to wrap sorted sets with synchronized access, it enhances the flexibility and safety of your code in concurrent environments. This method is particularly valuable in scenarios where you need to manage shared resources or ensure thread-safe access to sorted data, improving the robustness and maintainability of your Java applications.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top