views:

41

answers:

2

I have written a method which should only be called on a particular thread. Is there a standard annotation or note which should be added to the method's javadoc to denote this?

+1  A: 

Don't know of any such standard annotations. Java Concurrency in Practice deals with the question in its section 4.5: Documenting Synchronization Policies. A few hints which hopefully help you make your documentation clear and useful:

At the very least, document the thread safety guarantees made by a class. Is it thread-safe? Does it make callbacks with a lock held? Are there any specific locks that affect its behavior? Don't force clients to make risky guesses. If you don't want to commit to supporting client-side locking, that's fine, but say so. If you want clients to be able to create new atomic operations on your class, as we did in Section 4.4, you need to document which locks they should acquire to do so safely. If you use locks to guard state, document this for future maintainers, because it's so easy - the @GuardedBy annotation will do the trick. If you use more subtle means to maintain thread safety, document them because they may not be obvious to maintainers.

They also use some annotations, which are not standard, but recommended by them (see Appendix A). However, for methods they only offer variations of @GuardedBy, which is not applicable to your case.

I recommend just clearly documenting the requirement in plain Javadoc.

Péter Török
A: 

In my opinion, the best way to handle it is to remove the requirement. Change the method to private and rename it slightly by adding the word Workload or Internal or something. Then create a new public method with the same signature. Have this method check to see if you are on the correct thread. If you are, you can just execute the private method. If not, then schedule the private method to be executed on the correct thread. This way, the user of the API doesn't have to worry about threading and can just call the method.

Then, there is nothing to specify in the javadoc, although it is still useful to include this information in the description of the public and private methods.

This is the pattern I use when I need something executed on the EDT:

/**
 * Executes something on the EDT with the crazy argument specified.  If this is
 * called outside of the EDT, it will schedule the work to be done on the EDT
 * as soon as possible. The actual work of this method is found in
 * {@link #executeSomethingInternal(int)}.
 *
 * @argument crazyArgument some crazy argument
 */
public void executeSomething(int crazyArgument) {
  if (SwingUtilities.isEventDispatchThread()) {
    this.executeSomethingInternal(crazyArgument);
  } else {
    Runnable r = new Runnable() {
      private int crazyArgument;

      public Runnable setCrazyArgument(int crazyArgument) {
        this.crazyArgument = crazyArgument;
        return this;
      }

      @Override
      public void run() {
        this.OuterClass.executeSomethingInternal(this.crazyArgument);
      }
    }.setCrazyArgument(crazyArgument);
    SwingUtilities.invokeLater(r);
  }
}

/**
 * This method actually does the work.  It is guaranteed by this class to
 * always get called on the EDT.  Users of this API should call
 * {@link #executeSomething(int)}.
 */

private void executeSomethingInternal(int crazyArgument) {
  // do work here
}
Erick Robertson
To really drive the point home, you might want to use an assertion in the `executeSomethingInternal` method, too, like `assert SwingUtilities.isEventDispatchThread()`
gustafc
Being a private method, `executeSomethingInternal` can only be called from within the same class. If all of the calls are in `executeSomething`, then there is no way that `executeSomethingInternal` can ever be called outside of the EDT. The assertion would ensure that future programmers do not violate this willfully or without regard for the design.
Erick Robertson
Even private methods require documentation, unfortunately.
Alison
@Alison: Remove the requirement that it can only be run on the EDT, not remove the requirement for documentation. As you can see, I actually included documentation in the example code.
Erick Robertson