Example 1: Hello World
- In the snippet below, the constructor, HelloWorldThread(), and main() method both run on the main thread.
- The methods run() and helloworld() both run on the helloWorldThread.
- @ThreadConfined annotations are used to document the above threading model.
- Running CheckThread on the example below will not produce any errors.
import org.checkthread.annotations.*;
public class HelloWorldThread extends Thread {
@ThreadConfined(ThreadName.MAIN)
public HelloWorldThread() {
//runs on main thread
super();
start();
}
@ThreadConfined("helloWorldThread")
public void run() {
// runs on hello world thread
helloworld();
}
@ThreadConfined("helloWorldThread")
public void helloworld() {
// runs on hello world thread
System.out.println("Hello World!");
}
@ThreadConfined(ThreadName.MAIN)
public static void main(String[] args) {
// runs on main thread
new HelloWorldThread();
}
}
CheckThread Output: No errors
Example 2: Hello World With a Class Annotation
- If a method does not have a @ThreadConfined, CheckThread will look for an annotation at the method's class definition.
- This avoids "annotation clutter" in Java code.
- Generally most Java classes will have a significant portion of their methods run on the same thread, so only a few annotations will be necessary.
- From a thread policy standpoint, this example is equivalent to the previous example.
import org.checkthread.annotations.*; @ThreadConfined(ThreadName.MAIN) public class HelloWorldThreadClassAnnotation extends Thread { public HelloWorldThreadClassAnnotation() { // runs on main thread super(); start(); } @ThreadConfined("helloWorldThread") public void run() { // runs on hello world thread helloworld(); } @ThreadConfined("helloWorldThread") public void helloworld() { // runs on hello world thread System.out.println("Hello World!"); } public static void main(String[] args) { // runs on main thread new HelloWorldThread(); } }
CheckThread Output: No errors
Example 3: Hello World With a Bug
- In the next example, the Java developer goofs and incorrectly calls helloworld() from the main thread.
- As it is defined, helloworld() is only supposed to run on the "helloWorldThread", not the main thread.
- In this example, the implementation of helloworld() is doing a simple print out, but in practice this method could be loading a driver or other resource that must be called on a specific thread.
- Running CheckThread on this example will produce an error.
import org.checkthread.annotations.*; @ThreadConfined(ThreadName.MAIN) public class HelloWorldThreadWithBug extends Thread { public HelloWorldThreadWithBug() { // runs on main thread super(); start(); helloworld(); // THREAD BUG HERE!!! } @ThreadConfined("helloWorldThread") public void run() { // runs on hello world thread helloworld(); } @ThreadConfined("helloWorldThread") public void helloworld() { // should run on hello world thread System.out.println("Hello World!"); } public static void main(String[] args) { // runs on main thread new HelloWorldThread(); } }
CheckThread Output:
Thread policy mismatch error in HelloWorldThreadWithBug
calling helloworld
Example 4: Hello World Modified
- In the next example, the Java developer decides that helloworld() can run safely on any thread. The Java developer makes this decision based on the implementation of the method.
- The Java developer adds the @ThreadSafe annotation to the helloworld() method.
- CheckThread will no longer throw an error.
import org.checkthread.annotations.*; @ThreadConfined(ThreadName.MAIN) public class HelloWorldThreadWithBugFixed extends Thread { public HelloWorldThreadWithBugFixed() { // runs on the main thread super(); start(); helloworld(); // OK } @ThreadConfined("helloWorldThread") public void run() { // runs on hello world thread helloworld(); // OK } @ThreadSafe public void helloworld() { // this method can run on any thread System.out.println("Hello World!"); } public static void main(String[] args) { // runs on main thread new HelloWorldThread(); } }
CheckThread Output: No errors
Example 5: Simple Swing Code
- A common threading bug when working with Swing is to inadvertantly call a Swing method on the wrong thread (any thread other than the event-dispach thread).
- This bug can lead to sporadic behavior (e.g. painting issues, gray windows, etc) that is difficult to track down.
- The following example demonstrates how this bug can be caught at static analysis time by treating the Java code with the thread policy annotations.
- ThreadName.EDT is a "pre-canned" string representing the Event-Dispatch Thread within @ThreadConfined annotations.
// some java class import org.checkthread.annotations.*; @ThreadConfined(ThreadName.MAIN) public void method1() { //THREADING BUG! Calling method2 from main thread
method2();
}
@ThreadConfined(ThreadName.EDT) public void method2() { // should only run on EDT thread
jButton.setBackground(...) }
Running CheckThread analyzer on this code would throw the following error:
Thread policy mismatch error calling method2 from method1