通過Profiling工具看結果:
方法 運行時間
testOne 0.055764
testTwo 0.043821
testThres 0.132451
也就是說,jdk 1.5的for/each循環是最慢的。有點不相信。開頭覺得是因為賦值造成的,但后來在另兩個方法里面加上賦值語句,依然是for/each最慢。比較有趣的結果。
從代碼清晰角度,用for/each消耗多一點點時間似乎也無所謂。但是,另兩種代碼也不見得“不清晰”,呵呵。看著辦了。
本文只作很簡要介紹,可視作備忘參考。
TPTP是eclipse官方的profiling插件,初步使用下感覺功能強大。
下載安裝: 在http://www.eclipse.org/tptp/下載,我選擇All-Runtime,然后像其它插件一樣解壓到eclipse的目錄,然后允許eclipse -clean來刷新一把。
使用:
常用的profiling簡單來講就對程序運行進行記錄,然后從數據中分析哪些方法運行時間長,哪些對象吃內存多,哪些類的實例多等等。一個比較好的使用入門sample在這里: http://www.eclipse.org/tptp/home/documents/tutorials/profilingtool/profilingexample_32.html 我就不羅嗦了。
值得多講的是Remote Profiling,就是遠程剖析。實現的原理是在遠程機器上運行一個代理進程,要被遠程剖析的程序或者Application Server啟動的時候加一個JVM參數來識別這個代理進程,兩者相互作用,代理就可以把收集到的信息發給在遠程的一方(就是運行著eclipse的一方)。
因此要實現Remote Profiling,還要在目標機器上裝一個agent。 -->
下載安裝:http://www.eclipse.org/tptp/home/downloads/drops/TPTP-4.0.1.html 選擇對應操作系統的Agent Controller下載,選擇Runtime即可。
下載后,閱讀依照getting_started.html的說明來安裝即可,這里簡述一下:
1、 把它的bin目錄放到PATH里面
2、 運行一下SetConfig來設置參數,注意如果想讓除本地localhost意外所以機器都訪問的話,要注意設置Network Access Mode,默認是localhost的。
3、 運行RAStart來啟動代理(Linux下)
4、 服務器端程序(例如tomcat)啟動的JVM參數里面加入-XrunpiAgent:server=enabled即可(還有其它參數值參見文檔)
5、 然后就可以在遠程用eclipse來啟動一個Profiling進程來attach到這個agent controller了。效果和在eclipse里面直接profile應用程序一樣。
Sometimes, it seems excessive to pay the cost of synchronization just to read or write an instance field or two. After all, what can go wrong? Unfortunately, with modern processors and compilers, there is plenty of room for error:
Computers with multiple processors can temporarily hold memory values in registers or local memory caches. As a consequence, threads running in different processors may see different values for the same memory location!
Compilers can reorder instructions for maximum throughput. Compilers won't choose an ordering that changes the meaning of the code, but they make the assumption that memory values are only changed when there are explicit instructions in the code. However, a memory value can be changed by another thread!
If you use locks to protect code that can be accessed by multiple threads, then you won't have these problems. Compilers are required to respect locks by flushing local caches as necessary and not inappropriately reordering instructions. The details are explained in the Java Memory Model and Thread Specification developed by JSR 133 (see http://www.jcp.org/en/jsr/detail?id=133). Much of the specification is highly complex and technical, but the document also contains a number of clearly explained examples. A more accessible overview article by Brian Goetz is available at http://www-106.ibm.com/developerworks/java/library/j-jtp02244.html.
NOTE
The volatile keyword offers a lock-free mechanism for synchronizing access to an instance field. If you declare a field as volatile, then the compiler and the virtual machine take into account that the field may be concurrently updated by another thread.
For example, suppose an object has a boolean flag done that is set by one thread and queried by another thread. You have two choices:
Use a lock, for example:
public synchronized boolean isDone() { return done; }
private boolean done;
(This approach has a potential drawback: the isDone method can block if another thread has locked the object.)
Declare the field as volatile:
public boolean isDone() { return done; }
private volatile boolean done;
Of course, accessing a volatile variable will be slower than accessing a regular variablethat is the price to pay for thread safety.
NOTE
![]() |
Prior to JDK 5.0, the semantics of volatile were rather permissive. The language designers attempted to give implementors leeway in optimizing the performance of code that uses volatile fields. However, the old specification was so complex that implementors didn't always follow it, and it allowed confusing and undesirable behavior, such as immutable objects that weren't truly immutable. |
In summary, concurrent access to a field is safe in these three conditions:
The field is volatile.
The field is final, and it is accessed after the constructor has completed.
The field access is protected by a lock.