In this week, I want to ensure all guys know about some synchronizing skill.
DON'T DO:
1. Synchronizing on String:
For example, we pass in a string "abcdef" created previously by:
String xxx="abcdef";
into the function session,
JVM would get the "abcdef" String Object in the String pool in Perm Gen. If there is more than one "abcdef" String in the String Pool. It may causes all String "abcdef" obtaining the lock, it may causes a lot of unexpected errors if there are also some critical sessions using "abcdef" as the synchronizer, causing race condition.
2. Synchronize on Numerical wrapper, like Integer(),Long(),Double()
In fact, the JLS specified a certain range of number that always return the same instance when called.
For example,
It seems that two thread would be obtained their lock successfully, BUT, in fact, for sometime, threadOne or threadTwo would be blocked by chance as Integer one and Integer two are actually refer to the same instance in JVM Heap.
For the above, I suggest to create a brand new Object to peform the locking.
Like here:
Object lock=new Object();
3. Forget to do the Synchronize after using synchronized collections,like ConcurrentHashMap(), Collections.synchronizedMap(new HashMap())
By using these data structures, we can only ensure the thread Safety during get/put.
After we get the object from the data structure, you must use lock explicitly to ensure the thread safety issue.
DO:
1. Use JSR-166 Concurrent API.
There are some concurrent API available after Java 5, they are CountDownLatches, CyclicBarrier, Semaphore..
List of API is as below:
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html
2. Consider Lock API .
Java has an API java.util.concurrent.locks that provides more features than synchronized. Statistically , it is more scalable than sychronized during high load.
Moreover, it provides a more flexible API and a provides a fair locking.
3. Use ArrayBlockQueue/LinkedBlockQueue/BlockDeque for Producer/Consumer pattern.
Please don't re-invent the wheel. Use the updated implementation from Java.
(LMAX Disruptor seems a more interested library recently. The Ring Buffer really makes it attractive for low latency dispatching/thread communication )
4. Follow the lock Sequence.
Avoid the deadlock.
This 101 would be updated when I have more ideas in mind.
Welcome everybody suggesting some pitfalls are required to beware for the Thread Safety.
2013年5月27日 星期一
2013年5月16日 星期四
Java 7 Try-with-Resource
最近的Refactoring Project真是令人發悶,由於 Upgrade Project 是包含了 Java 5-->Java 7 的Update, 我可以測試一下 Java 7 的 try with Resource.
Try-With-Resource 是指 Java 在 嘗試 Initialize Resource 的時候的動作:
1. Object Initialized successful -> Close the resource
2. Object Initialized failed -> Close the resource
Java 7: static String readFirstLineFromFile(String path) throws IOException
{ try (BufferedReader br = new BufferedReader(new FileReader(path)))
{ return br.readLine(); } }
Before Java 7: static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException
{ BufferedReader br = new BufferedReader(new FileReader(path));
try { return br.readLine(); }
finally { if (br != null) br.close(); } }
比較一下,大家可以發現沒有Try-with-Resource 沒有了 finally 關上 BufferedReader 的 Coding.
Resource 只需要 implements AutoCloseable, 便可以以使用 這種 syntactic sugar 了.
其實這種 Syntax , 在 C# 一早便已存在(Using())
Try-With-Resource 是指 Java 在 嘗試 Initialize Resource 的時候的動作:
1. Object Initialized successful -> Close the resource
2. Object Initialized failed -> Close the resource
Java 7: static String readFirstLineFromFile(String path) throws IOException
{ try (BufferedReader br = new BufferedReader(new FileReader(path)))
{ return br.readLine(); } }
Before Java 7: static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException
{ BufferedReader br = new BufferedReader(new FileReader(path));
try { return br.readLine(); }
finally { if (br != null) br.close(); } }
比較一下,大家可以發現沒有Try-with-Resource 沒有了 finally 關上 BufferedReader 的 Coding.
Resource 只需要 implements AutoCloseable, 便可以以使用 這種 syntactic sugar 了.
其實這種 Syntax , 在 C# 一早便已存在(Using())
2013年5月13日 星期一
[Unit Testing]Ant with JoCoCo
我需要寫不同的JUnit Test Case 去 Test 不同的DAO 和 Persistence Unit.
公司的要求相當低:
1. 不講究Code Coverage.
2. 有部份同事為左方便,從來沒有Test 過其他 Create , Retrieve , and Update Function.( Code Coverage below 10%)
3. 用 DB 現成Data, 因為Data 會在很多時候變動,使 Unit Test Rely on DB Data. 不夠獨立性。
我本着 Tech Geek 的心態,為左嘗試不同的小技術,就把他們的 ANT Script 進行小修改:
1. 首先,在 build.xml 修改,加入 xmlns:jacoco="antlib:org.jacoco.ant" 。
<project name="Impl" default="default" basedir="." xmlns:jacoco="antlib:org.jacoco.ant">
2. 加入 JaCoCo 的 Task Def
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath path="lib/jacocoant.jar" />
</taskdef>
3. 把 需要行 Code Coverage 的 Java Task 用 <jacoco:coverage></jacoco:coverage> 包上。
4. 再將 已 Compile 好 的.class path 和 src file path 在紅的地方填上。
<target name="test-suite" depends="test-compile" description="Execute unit tests suite">
<echo> Test classpath ${proj.test.classpath}</echo>
<jacoco:coverage>
<java fork="yes" classname="org.junit.runner.JUnitCore">
<classpath>
<path refid="proj.test.classpath"/>
</classpath>
<arg line="com.xzxxx.abcd.ordermanagement.persistence.impl.test.TestTradeHistoryHibernatePersistence" />
</java>
</jacoco:coverage>
<jacoco:report>
<executiondata>
<file file="jacoco.exec"/>
</executiondata>
<structure name="Example Project">
<classfiles>
<fileset dir="build\classes"/>
</classfiles>
<sourcefiles encoding="UTF-8">
<fileset dir="src\java"/>
</sourcefiles>
</structure>
<html destdir="report"/>
</jacoco:report>
</target>
5. 最後,便是 行 ant <你的 target-name>
6. Report 會在 Report Directory Generate 出來。
HK Coding Style below.
Ant: http://ant.apache.org/
JaCoCo: http://www.eclemma.org/jacoco/
訂閱:
意見 (Atom)