當我們在使用多執行緒在執行程式時,如果有使用到存取共享變數時通常都會進行 synchronized 或是 lock 住,但是這樣做的話在執行多執行緒的效能就會變差,因為都要去等待其它的執行緒執行完之後才能進行執行。使用 Immutable 物件的主要目的是規定物件的內容在建立之後就不能修改,這樣就不會有不同執行緒存取到相同變數需要等待的問題出現,這樣做的話在執行緒執行的速度也會變快很多,但是要先確認需求才能判斷程式是否能修改成 Immutable 的方式去執行。
以下就寫一個使用 Immutable 的物件去執行多執行緒的程式如下:
public class ExampleThread implements Runnable {
private User user;
public ExampleThread(User user) {
this.user = user;
}
@Override
public void run() {
System.out.println(this.user.getUserName() + " " + this.user.getPassword());
}
}
以上是執行緒的程式主要會接收 User 的物件,並且執行到 run 方法時會將,User 物件的使用者名稱和密碼印出來。這個 User 是 immutable 的物件,程式如下:
public class User {
private final String userName;
private final String password;
public User(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String getUserName() {
return userName;
}
public String getPassword() {
return password;
}
}
在 User 類別裡會把 userName 和 password 宣告成 final,除了在建構物件時可以設定使用者的名稱和密碼外,其它的地方都不能去做其它的修改,這樣才能保持 immutable,以下是主程式的寫法:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String args[]) {
ExecutorService es = Executors.newFixedThreadPool(5);
try {
for (int i = 0; i < 5; i++) {
es.execute(new ExampleThread(new User("user-" + i, "aaa")));
}
} catch(Exception e) {
throw new RuntimeException(e);
} finally {
es.shutdown();
}
}
}
在主程式裡當要執行到執行緒程式時就會建立一個 Immutable 的 User 物件指定使用者名稱以及密碼,這樣其它的執行緒就不會存取到共有的物件,避免了要寫 synchronized 的語法,執行的結果如下:
user-0 aaa
user-1 aaa
user-3 aaa
user-2 aaa
user-4 aaa