網頁

顯示具有 筆記 標籤的文章。 顯示所有文章
顯示具有 筆記 標籤的文章。 顯示所有文章

2010年2月24日 星期三

[Java] Concurrency in Swing

參考 Java TutorialsConcurrency in Swing 章節所寫的筆記。

一個好的 Swing 程式會利用 concurrency 去建立不會 "凍結" 的 UI — 無論程式正在做什麼,都會回應使用者的操作。

一個 Swing programmer 將需要處理以下三種類型的 thread:
  1. Initial thread:
    啟動應用程式的 thread
  2. Event dispatch thread:
    所有的 Event-handling 程式都位於此 thread,大部分與 Swing 互動的程式也在此 thread 上執行。
  3. Worker thread:
    也稱做 background thread,需要消耗較長時間的 task 位於此 thread。

一個 Swing 程式應該這樣寫:
  1. Initial thread 沒有太多事要做,它最主要的工作就是建立一個 Runnable 物件負責建立 GUI,並且將這個物件交由 event dispatch thread 負責執行。 
     
  2. 將建立 GUI 交由 event dispatch thread 負責的方法為 javax.swing.SwingUtilities.invokeLater 或著 javax.swing.SwingUtilities.invokeAndWait,這兩個 method 都傳入一個 Runnable 物件。它們的差別在於 invokeLater 只會將工作加入排程後便返回,而 invokeAndWait 將會等待工作執行結束後才返回。
         
  3. 在 Applet 中,應該在 init 方法中呼叫 invokeAndWait,否則 init 可能會在 GUI 建立完成前就返回,這將可能造成瀏覽器啟動 applet 時的問題。
         
  4. 在其他類型的程式中,建立 GUI 通常都是 initial thread 中的最後一項工作,因此無論呼叫 invokeLater 或 invokeAndWait 皆可。
  5. 一旦 GUI 建立完成,程式的主要運作就變成 event-driven。其中較短的 task 將交由 event dispath thread,較長的 task 則交給 worker thread。

2009年12月20日 星期日

[Java] 製作 Sign Applet

前言:

Applet 是用於網頁上的小程式,基於安全理由,它不允許你做任何的 IO 操作,(存取本機電腦 及 網路連線...等,只有存放該網頁的 server 例外)否則一旦開了惡意的 applet,電腦就如同中了木馬一般。

這種概念稱為 Sandbox,只允許你在盒子內部操作,所以無論你在盒子裡做了什麼事,都不會影響到盒子外的世界。如果有特殊的需求,可以使用 Sign Applet,在開啟程式前會先出現確認視窗,待使用者同意後,程式便能夠有較高的存取權限。

製作 Sign Applet 方法:

  1. 產生 key:
    keytool -genkey -keyalg RSA -alias "key_name"


    1. 如果 key store 目前並不存在,
      則必須設定 keystore 密碼;
      反之,如果先前已經設定過密碼,
      則此時就需要輸入先前所設定的密碼。
    2. 接著必須輸入一些基本資料,
      如: 姓名, 單位, 國碼, ... 等等,
      此處就不贅述了。
    3. 最後輸入 key 密碼,即可順利產生 key。

  2. 將 key 加入 applet 中:
    jarsigner "applet.jar" "key_name"
    此時需要依序輸入 key store 密碼與 key 密碼。 
  3.  Sign Applet 製作完成,
    此時連上嵌入此 Sign Applet 的網頁,
    即會跳出確認視窗,詢問是否同意進行操作。 
延伸說明:
  1. 在產生 keytool 時,如果沒有特別指定,
    將會存放在此: ~/.keystore
    註: 此處以 ubuntu 為例, Windows 作業系統將會在其他的位址。
    如果需要額外指定存放位址, 需加上參數 -keystore "path"。
  2. 列出目前已有的 key:
    keytool -list
  3. 檢查 jar 是否已經完成 Sign
    jarsigner -verify "applet.jar"

Java Access Modifiers

Visibility
public
protected
package
(default)
private
same class
Y
Y
Y
Y
non-subclass in the same package
Y
Y
Y
N
non-subclass outside the package
Y
N
N
N
subclass in the same package
Y
Y
Y
N
subclass outside the package
Y
Y
N
N

  1. Class 只有 public 和 package 兩種 modifiers。
  2. 表格中 subclass 的 visiblility 指的是使用繼承方式 access 該 member
  3. protected 所修飾之 member,若其 subclass outside the package,則在 subclass 中,該 member 為 private。
  4. sub-package 不算是 same package

Java Thread

Java 的 Thread 和 Process 一樣,共有五個 state,
分別是 New, Runnable, Running, Waiting/blocked/sleeping, Dead。

New - 當 thread's instance 已經建立,但是尚未呼叫 start(),
此時,這個 thread 仍然稱做 not alive。

(其他的 state 和 Process 幾乎相同,這裡就省略了)


接下來介紹有關操作 thread 所需要呼叫的 method。

start() - Thread's non-static method
將該 thread 從 New state 移至 Runnable state,
至此,該 thread 才成為一個 alive thread。

無論如何,同一個 thread 物件都只能 start() 一次,
否則將會產生 RuntimeException;
然而同一個 Runnable interface,
則可以經由 Thread's Constructor,建立並啟動多個 thread。

yield() - Thread's static method
將目前的 thread 由 Running state 移至 Runnable,
並且由 Runnable state 中,
選一 "相同" priority 的 thread 進入 Running state,
故有可能會選到原先的 thread。

由於 JVM 對於 priority 的實作未必確實為 1~10,
可能會有多個設定值對應到同一個 priority 的情形,
所以需要特別注意。

sleep() - Thread's static method
將目前的 thread 由 Running state 移至 Sleeping,
並等待指定的時間後,才會進入 Runnable。

並不是時間一到立刻進入 Running,
所以通常該 thread 的休息時間會較長於指定的時間。

若是在 synchronize block 中呼叫 sleep(),
則 thread 並不會釋放自己所擁有的資源。

join() - Thread's non-static method
暫停目前 thread 的執行,並等待指定的 thread 執行完畢後,
此 thread 才會回到 runnable state。

以下三個指令都必須在 synchronize block 中才可呼叫。

wait() - Object's non-static method
目前 thread 進入 Waiting,暫時釋放指定的資源。

當此 thread 經由 notify() or notifyAll() 叫醒後,
會送出 InterruptedException()。

另外,wait() 也有 over-loading 的版本,
提供最長等待時間作為參數。

notify() - Object's non-static method
叫醒某個正等待此物件之 thread。

叫醒的順序與 thread 進入 Wainting 的時間無關。

notifyAll() - Object's non-static method
叫醒所有正在等待此物件之 thread。

註: notify 與 notifyAll 所叫醒的 thread 只是回到 runnable,
而並不會立刻執行。