2010年9月29日 星期三

Eclipse Web Service Setting



參考以下:
http://www.eclipse.org/webtools/community/tutorials/BottomUpAxis2WebService/bu_tutorial.html


<

AxisAdminServlet Class not found exception occurs as deploying the web service.

問題簡述:
Eclipse Java EE IDE for Web Developers. (Build id: 20090621-0832)
建立 web service後, 啟動 Tomcat 5.5 顯示錯誤訊息
java.lang.NoClassDefFoundError: org/apache/http/HttpResponseFactory

解決方法:
從 Apache Axis2 官網中下載 axis2-1.5-bin.zip, 從zip檔案的lib目錄中複製httpcore-4.0.jar 至
該專案的 WEB-INF/lib 目錄中







2010年9月28日 星期二

Interview 建議的題目(09/27)

1. Describe Java's exception handling:
Exception handling is the technique of catching the exceptions that might be thrown some time in the future during runtime. Java offers robust exception handling solutions with the try-catch-finally construct. One of the most remarkable exception is when, during program execution, the time comes for a division by zero. This cannot be done and, therefore, Java throws an exception, specifically the ArithmeticException.

2. What's the purpose of the finally clause of a try-catch-finally statement?
A finally clause can be added to force the exception of statements that perform necessary cleanup.

3. Tell me about a case that finally cluase will be not executed?
There is none.

4. Name some OO design patterns you have used and how/why you used them?
TO-DO
Singleton? Abstract Factory?
Hibernate SessionFactory is singleton??
Spring framework is Proxy??

5. What is a Singleton?
a. It proposes that at any time, there can only be one instance of a singleton (object) created by the JVM.
b. The class's default constructor is made private, which prevents the direct instantiation of the object by other classes. At static modifier is applied to the instance method that returns the object as it then makes this method a class level method that can be accessed without creating an object.
c. Singletons can be used to create a Connection Pool. If programmers create a new connection object in every class that requires it, then it's clearly waste of resources. In this scenario by using a singleton connection class we can maintain a single connection object which can be used throughout the application,

6. What is a transient variable and why would you use one?
A variable that may not be serialized. (Temporary state of the object which need not be saved, something like process ID, or Time information)

7. What is serialization?
Serialization is a mechanism for persisting and retrieving an object, including its state to/from the persistant storage.
(http://619lucky.blogspot.com/2010/09/java-serializable-string-object-is.html)
String object also implements Serializable interface. Serializable interface doesn't have any mothed.

8. What are the components of JDBC?
Connection pool, data sources, statement, ResultSets.

9. What is a bind variable (for JDBC) and why should they, or should they not, be used?
A placeholder for a variable in a query.... should almost always be used to reduce the number of query parses executed by the database.

10. When do you use a Statement vx. a CallableStatement vs. a PreparedStatement?
CallableStatement for procedures.
PrepatedStatemnt for queries using bind variables.
Statement for non bound (no bind variable) queries.

11. What is a DataSource?
Interface javax.sql.DataSource
DataSource is a factory for connections to the physical data source that DataSource factory represents.
DataSource is the preferred means of getting a connection.
An object that implements DataSource will usually be registered with a naming service based on the JNDI (Java Naming and Directory API)
(http://download.oracle.com/javase/1.4.2/docs/api/javax/sql/DataSource.html)

12. What is connection pool?
When use a SQL ot other similar tool to connect to that database and act on the data, "getting the connection" and "logging in" is the part that takes the most of the time.

Cached connections are kept in a runtime object pool and can be used and reused as needed by the application. One way to implement the object pool is to make a simple hashtable of connection objects. However, a more flexible way to do it is to write a wrapper JDBC Driver that is an intermediary between the client application and database.
(http://java.sun.com/developer/onlineTraining/Programming/JDCBook/conpool.html)
.....

13. What's a reasonable limit on connection pool size for an average single application server?
I don't know.... 20?
....

14. Can that many connections cause problems for a database?
Yes(?) If the connection is persistent...?
(http://blog.powercam.cc/xms/doc/724)
(http://www.coderanch.com/t/216774/ORM/java/Too-many-Connections-Exception)

15. Is there a maximun number of connections limit defined in the database?
How do you change it?
( I don't know )

16. What is the Connections API and what are the advantange of using it?
The Connections framework provides a well-designed set for sorting and manipulating a group of data (a collection).
(http://www.allapplabs.com/java/java_collection_framework.htm)
a. The collection interface is a group of objects, which duplicates allowed.
b. Set extends Collection but NOT allow duplicates.
c. List extends Collection also, it allows duplicates and introduces positioning indexing.
d. Map extends neither Set nor Collection.
Interface
Implementation
Historical
Set
HashSet

TreeSet


List

ArrayList

LinkedList
Vector
Stack
Map
HashMap

Treemap

Hashtable
Properties

ArrayList是List(列表),数据是有序的,可以有重复元素 HashSet是Set(集合),数据没有顺序,没有重复元素,元素搜索速度快 
17. Is Iterator inthe Collections API a class or an interface?
interface

18. What's the difference between a HashSet and an ArrayList?
HashSet can't have duplicate key/value, ArrayList can.

19. What's the difference between a HashSet and a HashMap?
a. HashSet doesn't allow duplcate, it maintains a unique list.
b. HashMap allows null for both keys and value, it's unsynchronized.
A HashMap provides fast access to a mapping from a unique key to a value. Keys are unordered which makes it faster than the TreeMap where the keys are ordered.
A HashSet is fast access to unique value only (there are no keys because it is not a mapping it's just the values). HashSet values are unordered which makes it faster than the TreeSet where the values are ordered.

20. Give an example of when you would use a HashMap?
If you may have null value in the collection, and the keys are unique but not in order...

21. What object do you use to determine if a user posesses a J2EE Role?
HttpRequest

22. What's the difference between an Integer and an int?
Object/Primitive
Object is using memory in Heap, Primitive is using memory in Stack.
(Check out Heap/Stack http://619lucky.blogspot.com/2010/09/java-stack-and-heap.html)

23. What methods are available on an int?
none.

23. What class do you use to convert between Integers, ints and Strings?
Integer

24. Are the methods you use to convert between Integers and ints class methods or instance methods?
Class method.

25. What does it mean for a method to be static?
Static methods use no instance variables of any object of the class. if you define a method to be static, you will be given a rude message by the compiler if you try to access any instance variables. You can access static variables, but except for constants.
Static methods typically take all the data from parameters and compute something from those parameters (with no reference to variables).
Static method is typical of methods which do some kind of generic calculation. A good example of this are the many uility methods in the predefined Math class.

宣告 method 時,如果前面加上 static 的修飾字,就會使得此 method 變成是 class method。對 class method 而言,永遠只佔用一塊記憶體,而且此記憶體空間是在此 class 一被載入進記憶體之後就立刻配置的,就如同此 method 是與該 class 本身相關,而不是與該 class 的 instance 相關。


26. What class do you use to manipulate Date objects in Java?
Calendar

27. What class do you use to format Date objects in Java?
DateFormat(abstract class) or SimpleDateFormat -subclass of DateFormat.


28. What is the difference between SAX based and DOM based XML parsing?
SAX is event based. DOM is tree navigation based.

29. When would you use one over the other?
SAX for XML based event processing. Large documents or memory constrained System.
DOM for XML document editing.

30. Tell about any XML binding tools you've used, or any other parsing techniques.
JAXB (Marschalling and UnMarshalling, Factory)....(?)

31. Schema and DTD
?????

32. What must a class do to implement an interface?
It must provide all of the methods in the interface and identify the interface in its implements clause.

33. What is an interface and what are they used for?
a. Capturing similarities among unrelated classes without arficially forcing a class relationship.
b. Declaring methods that one or more classes are expected to implement.
c. Revealing an object's programming interface without revealing its class.

34. Let's make up a system where we need to track electricity usage in a building. We have some objects that consume electricity (Monitor and Printer). We want to add an interface to the system that will define a method for determining the monitor or printer's electrical consumption.

Question: What should be a good name for this interface?
Answer: (通常是形容詞)something like Powerable, PluggedIn, ElectricityConsumer
Question: What would be a good name for a method in this interface and what would the method do?
Answer: (通常是動詞)getConsumption() returns the amount of power consumed.
Question: Let's create an Exception that will be thrown by the getConsumption method when the object is not plugged in. What's good name for that exception?
Answer: NotPluggedInException. PlugInFailException.

35.

2010年9月27日 星期一

HashMap, HashSet, HashTable 等等的 Hash Collection

Hashtable類
Hashtable繼承Map接口,實現一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value
添加數據使用put(key, value),取出數據使用get(key),這兩個基本操作的時間開銷為常數。
Hashtable通過initial capacity和load factor兩個參數調整性能。通常缺省的load factor 0.75較好地實現了時間和空間的均衡。增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作。
使用Hashtable的簡單示例如下,將1,2,3放到Hashtable中,他們的key分別是”one”,”two”,”three”:
Hashtable numbers = new Hashtable();
numbers.put(“one”, new Integer(1));
numbers.put(“two”, new Integer(2));
numbers.put(“three”, new Integer(3));
要取出一個數,比如2,用相應的key:
Integer n = (Integer)numbers.get(“two”);
System.out.println(“two = ” + n);
由於作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現hashCode和equals方 法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相 同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,如 果兩個不同對象的hashCode相同,這種現象稱為沖突,沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的hashCode()方法,能加快哈希 表的操作。
如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時複寫equals方法和hashCode方法,而不要只寫其中一個。
Hashtable是同步的。

HashMap類
HashMap和Hashtable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key。但是將HashMap視為Collection時(values()方法可返回Collection),其叠代子操作時間開銷和HashMap 的容量成比例。因此,如果叠代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。

WeakHashMap類
WeakHashMap是一種改進的HashMap,它對key實行“弱引用”,如果一個key不再被外部所引用,那麽該key可以被GC回收。



HashSet請參考對Set的描述

Set是一種不包含重複的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。
Set的構造函數有一個約束條件,傳入的Collection參數不能包含重複的元素。  
請註意:必須小心操作可變對象(Mutable Object)。如果一個Set中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題。
兩個通用Set實現是HashSet 和TreeSet。要決定用哪一個,那是非常簡單明了的。 HashSet 要快得多 (對大多數操作是常數時間之於對數時間(constant time vs. log time)), 但不提供排序保證。如果你需要使用 SortedSet 中的操作,或者按順序叠代對你來說是重要的,那麽請使用 TreeSet。 否則,使用 HashSet。 在大多數時間都不使用 HashSet ,對你來說是個公平的賭博。

關於 HashSet,有一件事應該牢記,即就條目數和容量之和來講,叠代是線性的。因此,如果叠代性能很重要,那就應該慎重選擇一個適當的初始容量。容量選得 太大,既浪費空間,也浪費時間。 默認的初試容量是101, 一般來講,它比你所需要的要多。可以使用 int 構造函數來指定初始容量。要分配 HashSet 的初始容量為17:

Set s= new HashSet(17);

HashSets 另有一個稱作 裝載因數(load factor) 的"調整參數(tuning parameter)" 。如果你非常在乎你的 HashSet 的空間的使用,請閱讀 HashSet 文本以獲取詳細信息。否則,就使用默認值吧。如果你接受默認裝載因數,但你確實又想指定初始容量,那麽,選一個大約是你期望你的 Set 將增長到的容量的兩倍的數。如果你的猜測不著邊,它也可以增長,或只是浪費一點空間。但都沒有大問題。如果你知道有關正確尺寸的一個最佳值,用它吧;如果 不知道,那就使用一個舊的值,或使用一個偶數值。它真的不是非常重要。這些事情只能使 HashSet 稍稍變好一點點。

TreeSet 沒有調整參數。除 clone 之外,HashSet 和 TreeSet 都僅有那些由它們各自的接口所要求的操作 (Set 和 TreeSet),而沒有任何別的操作。



******************************* 我 是 分 隔 線 *******************************

http://www.pakzilla.com/2009/08/24/hashmap-vs-hashtable-vs-hashset/

Hashtable

Hashtable is basically a datastructure to retain values of key-value pair.

  • It didn’t allow null for both key and value. You will get NullPointerException if you add null value.
  • It is synchronized. So it comes with its cost. Only one thread can access in one time
Hashtable;
cityTable = new Hashtable();
cityTable.put(1, "Lahore");
cityTable.put(2, "Karachi");
cityTable.put(3, null); /* NullPointerEcxeption at runtime*/

System.out.println(cityTable.get(1));
System.out.println(cityTable.get(2));
System.out.println(cityTable.get(3));

HashMap

Like Hashtable it also accepts key value pair.

  • It allows null for both key and value
  • It is unsynchronized. So come up with better performance
HashMap productMap = new HashMap();
productMap.put(1, "Keys");
productMap.put(2, null);

HashSet

HashSet does not allow duplicate values. It provides add method rather put method. You also use its contain method to check whether the object is already available in HashSet. HashSet can be used where you want to maintain a unique list.

HashSet stateSet = new HashSet();
stateSet.add ("CA");
stateSet.add ("WI");
stateSet.add ("NY");

if (stateSet.contains("PB")) /* if CA, it will not add but shows following message*/
System.out.println("Already found");
else
stateSet.add("PB");

2010年9月26日 星期日

Java Serializable (String object is serialized)

Java中,什麽時候不能用Serializable?

舉個例子,你編寫了一款遊戲,保存記錄時把所有狀態一一保存非常麻煩,這時就可以使用Serializable(序列化接口),它的作用是可以將一個對象實例序列化,序列化後你可以選擇將它保存在你需要的位置。相對的,讀取後生成的對象所有屬性(除了設置為瞬時值的屬性)將和原對象的屬性相同(只是內存地址不同)。這樣可以方便的將一個java對象寫入到磁盤中,保存該對象的所有狀態!值得註意的是序列化的對象中包含的屬性和其他對象都需要實現序列化接口,不然無法正常序列化!在hibernate裡,並非所有的實體類必須實現序列化接口,因為在hibernate中我們通常是將基本類型的數值映射為數據庫中的字段。而基礎類型都實現了序列化接口(String也實現了)。所以,只有在想將一個對象完整存進數據庫(存儲為二進制碼),而不是將對象的屬性分別存進數據庫,讀取時再重新構建的話,就可以不用實現序列化接口。

2010年9月25日 星期六

Java Boxing(裝箱) and Unboxing(拆箱) (繼堆積堆疊之後)

Boxing(裝箱)跟Unboxing(拆箱)的關係在講之前還要再提一個萬物之母的類別 "Object"
Object是一種參考型別,也是所以類別的源頭。因此Object可以指向任何的參考型別。
但是當Object指向數值型別時,那會怎麼樣?

int
數值 = 100 ;
object o = 數值 ;

參考型別是擺在堆積裡,數值型別是擺在堆疊裡。那...Object指向數值型別到底該擺哪?

這個時候,就會將100從堆疊中複製一份到堆積中的盒子裡,然後o這個物件參考指向這個盒子。這種將堆疊中的值複製到堆積中的行為,就叫Boxing(裝箱)。反過來說,將堆積中的值,複製到堆疊中的行為,就叫Unboxing(拆箱)

int 值 = (int) o ; // 將o拆箱


Java Stack(堆疊, 棧) and Heap(堆積, 堆)

stack 和 heep 都是內存的一部分
stack 空間小,速度比較快, 用來放對象的引用
heep 大,一般所有創建的對象都放在這里。

堆疊(stack)可以想像成一個一個疊起來的盒子,數值型別的變數就一個一個放在盒子內。當變數生命周期結束時,盒子就會被移走。

堆積(heap)就像一個空地內亂七八糟的擺了一堆盒子,然後盒子上有標明這個盒子目前是屬於誰在使用的(可以很多人使用同一個盒子)。每當new 出一個物件,例如: Customer c = new Customer(); 物件參照 c 就擺放在堆疊中的盒子裡,而new出來的物件Customer()就在堆積中找一個沒人用的空盒子來擺。當c的生命周期結束,也就是Customer()沒人使用時,堆積中的盒子就會被註明為沒人使用,系統會不定時的把沒人使用的盒子清空。

棧(stack): 是一個先進後出的數據結構,通常用於保存方法(函數)中的參數,局部變量.
在java中,所有基本類型和引用類型都在棧中存儲.棧中數據的生存空間一般在當前scopes內(就是由{...}括起來的區域).
堆(heap):是一個可動態申請的內存空間(其記錄空閑內存空間的鏈表由操作系統維護),C中的malloc語句所產生的內存空間就在堆中.
在java中,所有使用new xxx()構造出來的對象都在堆中存儲,當垃圾回收器檢測到某對象未被引用,則自動銷毀該對象.所以,理論上說java中對象的生存空間是沒有限制的,只要有引用類型指向它,則它就可以在任意地方被使用.

差別:
1. 棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設置棧或堆。
2. 棧的優勢是,存取速度比堆要快,僅次於直接位於CPU中的寄存器。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。另外,棧數據可以共享,詳見第3點。堆的優勢是可以動態地分配內存大小,生存期也不必事先告訴編譯器,Java的垃圾收集器會自動收走這些不再使用的數據。但缺點是,由於要在運行時動態分配內存,存取速度較慢。
3. Java中的數據類型有兩種。
一種是基本類型(primitive types), 共有8種,即int, short, long, byte, float, double, boolean, char(註意,並沒有string的基本類型)。這種類型的定義是通過諸如int a = 3; long b = 255L;的形式來定義的,稱為自動變量。值得註意的是,自動變量存的是字面值,不是類的實例,即不是類的引用,這里並沒有類的存在。如int a = 3; 這里的a是一個指向int類型的引用,指向3這個字面值。這些字面值的數據,由於大小可知,生存期可知(這些字面值固定定義在某個程序塊里面,程序塊退出後,字段值就消失了),出於追求速度的原因,就存在於棧中
另外,棧有一個很重要的特殊性,就是存在棧中的數據可以共享。假設我們同時定義:
int a = 3;
int b = 3;
編譯器先處理int a = 3;首先它會在棧中創建一個變量為a的引用,然後查找有沒有字面值為3的地址,沒找到,就開辟一個存放3這個字面值的地址,然後將a指向3的地址。接著處理int b = 3;在創建完b的引用變量後,由於在棧中已經有3這個字面值,便將b直接指向3的地址。
這樣,就出現了a與b同時均指向3的情況。特別註意的是,這種字面值的引用與類對象的引用不同。
假定兩個類對象的引用同時指向一個對象,如果一個對象引用變量修改了這個對象的內部狀態,那麽另一個對象引用變量也即刻反映出這個變化。
相反,通過字面值的引用來修改其值,不會導致另一個指向此字面值的引用的值也跟著改變的情況。
如上例,我們定義完a與b的值後,再令a=4;那麽,b不會等於4,還是等於3。在編譯器內部,遇到a=4;時,它就會重新搜索棧中是否有4的字面值,如果沒有,重新開辟地址存放4的值;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。
另一種是包裝類數據,如Integer, String, Double等將相應的基本數據類型包裝起來的類。這些類數據全部存在於堆中,Java用new()語句來顯示地告訴編譯器,在運行時才根據需要動態創建,因此比較靈活,但缺點是要占用更多的時間。
4.String是一個特殊的包裝類數據。即可以用String str = new String("abc");的形式來創建,也可以用String str = "abc";的形式來創建(作為對比,在JDK 5.0之前,你從未見過Integer i = 3;的表達式,因為類與字面值是不能通用的,除了String。而在JDK 5.0中,這種表達式是可以的!因為編譯器在後臺進行Integer i = new Integer(3)的轉換!)。
前者是規範的類的創建過程,即在Java中,一切都是對象,而對象是類的實例,全部通過new()的形式來創建。Java中的有些類,如DateFormat類,可以通過該類的 getInstance()方法來返回一個新創建的類,似乎違反了此原則。其實不然。該類運用了單例模式來返回類的實例,只不過這個實例是在該類內部通過 new()來創建的,而getInstance()向外部隱藏了此細節。那為什麽在String str = "abc";中,並沒有通過new()來創建實例,是不是違反了上述原則?其實沒有。

# public class Test {
# public static void main(String[] args) {
# String str1 = "abc";
# String str2 = "abc";
# String str3 = new String("abc");
# String str4 = new String("abc");
# //str1 str2
# if(str1 == str2) {
# System.out.println("str1 and str2 is stored as stack");
# }
# else {
# System.out.println("str1 and str2 is stored as heap");
# }
# //str3 str4
# if(str3 == str4) {
# System.out.println("str3 and str4 is stored as stack");
# }
# else {
# System.out.println("str3 and str4 stored as heap");
# }
# }
# }



运行结果如下:
str1 and str2 is stored as stack
str3 and str4 stored as heap

產生這種結果的原因:
1.編譯器在處理String str1="abc"時,會首先在棧中創建一個變量"abc",然後用str1指向"abc",然後處理String str2="abc",編譯器查找棧中已經存在了變量"abc",直接將str2指向已經存在的"abc"變量,所以str1==str2執行結果為 true;
2.編譯器在處理String str3=new String("abc")時,在堆中創建一個新的"abc"對象,然後用str3指向這個對象,然後處理String str4=new String("abc"),在堆中再次創建一個新的"abc"對象,然後用str4指向這個對象,所以str3和str4分別為不同對象的引用,執行 str3==str4為false;

Thread-Safe的理解與分析

⓪原創: 蕭沖
http://aftcast.pixnet.net/blog/post/23786004

何謂thread-safe? 這個問題我看過許多論壇都有討論過,都總讓人覺得不很滿意。在此,筆者想要用更logical的方式來把議題說清楚。首先,我要了解它的定義! 定義若都不明白就難以判別安不安全了!

thread是什麼呢? 可能也有人不太了解。就從這裡開始… 當cpu處理一段(區塊)的程式碼時,從開始的第一行程式碼來跑就算是thead的開始,直到區塊的最後一行程式結束,就算是thread的結束。所謂的「主thread」,在dos (或dos like)程式裡,就是指main( )這個函式的開始到結束的一個thread。而主thread以外的一個子thread則是指程式人員自行在主thread裡再定義一個「程式區塊」,並請cpu同步的去執行那個區塊。

由上面的thread的定義來看,我們可以進而推論所謂的multithread這個字其實是有三種情形的,哪三種呢?
1/ 相同的一個程式區塊,請cpu"分出多身"來執行它!
2/ 不同的程式區塊,請cpu各別分時的去執行每個區塊
3/ 混合以上二種情形

所以,當我們在討論多緒/多線程(multithread)的問題時,我們要先去了解問題是上面三類的哪一類。許多的情形下,都是指第一類!

我們再把「程式區塊」給解析一下。它可以是一個function,或是一個class,或是上述二者的混合體。因為function或是class都會使用到變數,於是多緒時變數的共享就成了一個很大的問題。這就是為什麼會有thread-safe的這個議題了!

到此為止,我們可以想像若一個程序(process / 主thread)裡,有大於等於一個子thread在跑,就會產生thread-safe的問題。以最簡單的情形來說,mainthread+user自定的一個thread。假設Button元件按下後會寫入一個item至memo元件裡,而同時間的一個thread則會取用memo裡的item。假想當thread在取用item做分析的時候,user不知情的按下button,那麼thread是否有可能會取到不正確的item? 若不經過特別的安全設定,肯定「取用」時時而會出問題!

因此,到底安全或不安全的根源就在那執行的區塊程式碼上了(以上例就是取用的過程)。我要補充一個重要的事,其實每一個thread都有自己的一個專屬stack,所以auto級(local)的區域變數是不會有共享的問題,因為它們都是存放在thread各自的記憶體空間內,彼此不甘擾。也就是說,若你的程式區塊中,所有使用到的變數都是local(auto)變數,那你這個區塊,或說這個thread,就算是thread-safe! 相反的,若你的區塊中有用到全域的變數,那麼你的這個thread就有可能是不安全。請注意看,是有可能,並非一定是。

如何把含有全域變數的thread分析出安全或不安全?其實這是很直覺的。比如說某全域變數int g被thread使用到,但整個thread裡只參考到一次,那算安全嗎? 答案是…安全。因為單一基本變數的一次存取cpu處理極快,不太會有衝突。又,若是某全域變數 struct tag 被參考到一次,那算安全嗎? 答案是…不太安全,因為一個結構體的存取可能涉及到多個微指令。進一步的用上面的例子來說,若int g被參考到2次(含)以上,那就肯定不安全了。比如說第一次是把g設成k,第二次把g再設給某變數i,若thread1正在處理第二次參考,而thread2在處理第一次參考。那thread1可能會得到意外的答案!

如何讓不安全的thread變成安全的?? 其實主要的方法有二類。


1/
存取共用全域變數時加上lock的機制,而這lock的機制在windows上可以使用mutex、criticalsection、event、semaphore等物件配合WaitForSingleObject或WaitForMultipleObject二個api來控制。其原理就是當某thread在取用資料時,其他的通通都停止並等待,直到該thread取用完。

2/ 把存取全域變數的動作通通交給某一個thread全全處理。比如說你有thread1,thread2,thread3。當要存取全域的struct變數時,thread2就把工作交給thread1做,然後自己停住等thread1完成,thread3也把工作交給thread1做,並等待… 。這原理應該容易理解,因為不安全的工作全都交給"單一"的thread來處理時,那份工作就安全了呀!當然,這也不禁讓我們覺得,這樣效能非常的差! 通通都在等thread1。 不過還好的是,若少少的用還ok,若許多的工作都交給某一thread順序來處理,那就真的沒意義了!而這種方式其實就是bcb或delphi裡的synchronize這個方法的處理方式!

後註: class 其實也像是一種function,所以class本身也是存在著安全與否的問題。倘若該class裡的menthod有用到全域的變數時,該class也算是不安全的! 而許多的VCL就是這類的class!

註2:
若什麼是auto變數、stack都還不清楚,請先自行google或查程式語言的書,這是很基本且重要但易被忽略的章節。