Java thread-safe example

Ví dụ về thread-safe trong Java , với 1 built-in class khá thường gặp là SimpleDateFormat .

(Ở đây viết dạng chạy với JUnit4 , ai chưa quen có thể copy lại thành hàm main() để chạy)

  @org.junit.Test
  public void testFormattingWithRunnable() {
    // FIXME - dq: To see the bug, use SimpleDateFormat statement
    final java.text.DateFormat df = new java.text.SimpleDateFormat("dd-MMM-yyyy");
    // final DateFormatter df = new vn.ducquoc.util.DateFormatter("dd-MMM-yyyy");
    final String[] testdata = { "01-Jan-1999", "14-Feb-2001", "31-Dec-2007" };
    Runnable runnables[] = new Runnable[testdata.length];
    org.junit.Assert.assertNotNull("Look at the results");
    for (int i = 0; i < runnables.length; i++) {
      final int i2 = i;
      runnables[i] = new Runnable() {
        public void run() {
          try {
            for (int j = 0; j < 12; j++) {
              String str = testdata[i2];
              String str2 = null;
              /* synchronized(df) */{
                Date d = df.parse(str);
                str2 = df.format(d);
              }
              System.out.println("EXPECTED " + str + " ACTUAL " + str2);
            }
          } catch (java.text.ParseException e) {
            throw new RuntimeException("Parse failed");
          }
        }
      };
      new Thread(runnables[i]).start();
    }
  }

 

.

 

Không chỉ Thread/Runnable bị vấn đề mà ngay cả các Callable cũng rứa:

  @org.junit.Test
  public void testParsingWithCallable() throws Exception {

    // FIXME - dq: To see the bug, use SimpleDateFormat statement
    final DateFormat df = new java.text.SimpleDateFormat("yyyyMMdd");
    // final DateFormatter df = new vn.ducquoc.util.DateFormatter("yyyyMMdd");

    Callable<Date> task = new Callable<Date>() {
      public Date call() throws Exception {
        return df.parse("20101010");
      }
    };

    // pool with 5 threads
    ExecutorService exec = Executors.newFixedThreadPool(5);
    List<Future<Date>> results = new ArrayList<Future<Date>>();

    // perform 12 date conversions
    for (int i = 0; i < 12; i++) {
      results.add(exec.submit(task));
    }
    exec.shutdown();

    org.junit.Assert.assertNotNull("Look at the results");
    for (Future<Date> result : results) {
      System.out.println(result.get());
    }
  }

 

.

 

 

.

 

Các cách chính để tránh vấn đề cho multi-thread (concurrency) :

1/ dùng từ khóa synchronized của Java cho block hoặc method

 

2/ tạo một đối tượng mới mỗi khi thực hiện tác vụ (bằng cách new , clone() , Class.newInstance() , … )

 

3/ dùng các biến thuộc lớp ThreadLocal của Java

 

.

Theo nguyên lý K.I.S.S thì có lẽ nên áp dụng cách 1 .

 

./.

About DucQuoc.wordpress.com

A coder, brother, and player at times...
This entry was posted in Coding, Marketing. Bookmark the permalink.

4 Responses to Java thread-safe example

  1. Actually, there is one or more other approaches, which are the ‘lower level’ of above approaches. For example, instead of ‘synchronized’ block we can use Lock of java.util.concurrent, such as ReentrantLock. Or use some AtomicInteger, AtomicReference instead of ThreadLocal. Or use ‘partial instances’ by getDateInstance() with some cache like ConcurrentHashMap (and maybe SoftReference/WeakReference)

    These ‘low-level’ approach is suitable when you want to know more about underlying techniques to handle the multi-thread, like mutex, semaphore, blockingQueue, nonBlocking algorithms… or when it (really) reaches the phase of performance optimization . The most use case is, to impress some guys who don’t even know “synchronized”, such as a non-technical manager :- ) .

  2. Pingback: Logging best practices | DucQuoc's Blog

  3. Pingback: Sprint end DoW | DucQuoc's Blog

  4. Pingback: Sprint end DoW | DucQuoc's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s