Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: added finally block CS

...

The execution order may differ depending on thread scheduling, however, Friday occurs just once in this case. Note that increasing the thread pool size from time to time is not a feasible option.

Compliant Solution (try-finally clause)

This compliant solution wraps the statements in the doSomething1() method of class DiaryPool in a try-finally block. The finally block restores the initial state of the thread local object days.

Code Block
bgColor#ccccff

public final class DiaryPool {
  // ...

  public void doSomething1() {
    exec.execute(new Runnable() {
      public void run() {
    	try {  
          Diary.setDay(Day.FRIDAY);
          diary.threadSpecificTask();
    	} finally {
    	  Diary.setDay(Day.MONDAY);	
    	}
      }
    });
  }
 
  // ...
}

This solution transfers the burden of maintainability to the client but is a good option when the Diary class cannot be refactored.

Compliant Solution (instance per call)

The class Diary does not use a ThreadLocal object in this compliant solution. Also, the class DiaryPool uses local instances of class Diary within the methods doSomething1() and doSomething2(). The Day is uniquely maintained by each instance of the Diary class. As multiple threads are allowed to share a Diary instance, the day field is declared static. Creating two Diary instances in class DiaryPool allows the first thread to work with the object instance having the current day as Friday and the other two threads to work with the object instance having the current day as Monday.

Code Block
bgColor#ccccff
public final class Diary {
  private static Day day;

  Diary() {
    day = Day.MONDAY; // Default	
  }

  private Day currentDay() {
    return day;
  }

  public void setDay(Day d) {
    day = d;
  }

  // Performs some thread-specific task
  public void threadSpecificTask() {
    // Do task ...
    System.out.println("The day is: " + currentDay());
  }
}

public final class DiaryPool {
  private final int NoOfThreads = 2; // Maximum number of threads allowed in pool
  private final Executor exec;

  DiaryPool() {
    exec = (Executor) Executors.newFixedThreadPool(NoOfThreads);
  }

  public void doSomething1() {
    final Diary diary = new Diary(); // First instance
    exec.execute(new Runnable() {
      public void run() {
        diary.setDay(Day.FRIDAY);
        diary.threadSpecificTask();
      }
    });
  } 

  public void doSomething2() {
    final Diary diary = new Diary(); // Second instance
    exec.execute(new Runnable() {
      public void run() {
        diary.threadSpecificTask();
      }
    });
  }

  public static void main(String[] args) {
    DiaryPool dp = new DiaryPool();
    dp.doSomething1(); // Thread 1, requires current day as Friday
    dp.doSomething2(); // Thread 2, requires current day as Monday 
    dp.doSomething2(); // Thread 2, requires current day as Monday
  } 
}

...