<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>



    聯系博主          博客地圖
               
           看了文章一,應該對線程有個初步的認識了,我再簡單的介紹一下線程使用中的一些內容.
    線程通過幾種機制進入 Java 程序。除了用 Thread 構造器中顯式創建線程之外,還可以用許多其它機制創建線程:
    · AWT 和 Swing
    · RMI
    · java.util.TimerTask 工具
    · servlet 和 JSP 技術
    我只是簡單的提一下后兩種.
    TimerTask.
    JDK 1.3 中,TimerTask 工具被引入到 Java 語言。這個便利的工具讓您可以稍后在某個時間執行任務(例如,即從現在起十秒后運行一次任務),或者定期執行任務(即,每隔十秒運行任務)。
    實現 Timer 類非常簡單:它創建一個計時器線程,并且構建一個按執行時間排序的等待事件隊列。
    TimerTask 線程被標記成守護程序線程,這樣它就不會阻止程序退出。
    servlet 容器創建多個線程,在這些線程中執行 servlet 請求。作為 servlet 編寫者,您不知道(也不應該知道)您的請求會在什么線程中執行;如果同時有多個對相同 URL 的請求入站,那么同一個 servlet 可能會同時在多個線程中是活動的。
    當編寫 servlet 或 JavaServer Pages (JSP) 文件時,必須始終假設可以在多個線程中并發地執行同一個 servlet 或 JSP 文件。必須適當同步 servlet 或 JSP 文件訪問的任何共享數據;這包括servlet 對象本身的字段。
    下面說一下共享數據的訪問,這也是線程的一個很重要的部分.
    要使多個線程在一個程序中有用,它們必須有某種方法可以互相通信或共享它們的結果。
    讓線程共享其結果的最簡單方法是使用共享變量。它們還應該使用同步來確保值從一個線程正確傳播到另一個線程,以及防止當一個線程正在更新一些相關數據項時,另一個線程看到不一致的中間結果。有關兩個關鍵字:synchronized 和volatile以及java鎖,我已經在上一篇文章里面提到了,這里我再深入的介紹一下.
    先復述一下java鎖,
    每個 Java 對象都有一個相關的鎖。同一時間只能有一個線程持有 Java 鎖。當線程進入
    synchronized 代碼塊時,線程會阻塞并等待,直到鎖可用,當它可用時,就會獲得這個鎖,然后執行代碼塊。當控制退出受保護的代碼塊時,即到達了代碼塊末尾或者拋出了沒有在 synchronized 塊中捕獲的異常時,它就會釋放該鎖。
    Java 鎖定合并了一種互斥形式。每次只有一個線程可以持有鎖。鎖用于保護代碼塊或整個方法,必須記住是鎖的身份保護了代碼塊,而不是代碼塊本身,這一點很重要。一個鎖可以保護許多代碼塊或方法。
    反之,僅僅因為代碼塊由鎖保護并不表示兩個線程不能同時執行該代碼塊。它只表示如果兩個線程正在等待相同的鎖,則它們不能同時執行該代碼。
    下面這個實例代碼展示就是后面這種情況. ,兩個線程可以同時不受限制地執行 setLastAccess() 中的 synchronized 塊,因為每個線程有一個不同的 thingie 值。因此,synchronized 代碼塊受到兩個正在執行的線程中不同鎖的保護。
    public class SyncExample {
    public static class Thingie {
    private Date lastAccess;
    public synchronized void setLastAccess(Date date) {
    this.lastAccess = date;
    }
    }
    public static class MyThread extends Thread {
    private Thingie thingie;
    public MyThread(Thingie thingie) {
    this.thingie = thingie;
    }
    public void run() {
    thingie.setLastAccess(new Date());
    }
    }
    public static void main() {
    Thingie thingie1 = new Thingie(),
    thingie2 = new Thingie();
    new MyThread(thingie1).start();
    new MyThread(thingie2).start();
    }
    }
    同步方法
    創建 synchronized 塊的最簡單方法是將方法聲明成 synchronized。這表示在進入方法主體之前,
    調用者必須獲得鎖:
    public class Point {
    public synchronized void setXY(int x, int y) {
    this.x = x;
    this.y = y;
    }
    }
    對于普通的 synchronized 方法,這個鎖是一個對象,將針對它調用方法。對于靜態 synchronized方法,這個鎖是與 Class 對象相關的監控器,在該對象中聲明了方法。
    僅僅因為 setXY() 被聲明成 synchronized 并不表示兩個不同的線程不能同時執行 setXY(),只要它們調用不同的 Point 實例的 setXY() 就可同時執行。對于一個 Point 實例,一次只能有一個線程執行 setXY(),或 Point 的任何其它 synchronized 方法。
    如以下代碼樣本所示,SimpleCache.java 使用 HashMap 為對象裝入器提供了一個簡單的高速緩存。
    load() 方法知道怎樣按對象的鍵裝入對象。在一次裝入對象之后,該對象就被存儲到高速緩存中,這樣以后的訪問就會從高速緩存中檢索它,而不是每次都全部地裝入它。對共享高速緩存的每個訪問都受到 synchronized 塊保護。由于它被正確同步,所以多個線程可以同時調用 getObject 和clearCache 方法,而沒有數據損壞的風險。
    public class SimpleCache {
    private final Map cache = new HashMap();
    public Object load(String objectName) {
    // load the object somehow
    }
    public void clearCache() {
    synchronized (cache) {
    cache.clear();
    }
    }
    public Object getObject(String objectName) {
    synchronized (cache) {
    Object o = cache.get(objectName);
    if (o == null) {
    o = load(objectName);
    cache.put(objectName, o);
    }
    }
    return o;
    }
    }
    由于線程執行的計時是不確定的,我們需要小心,以控制線程對共享數據的訪問。否則,多個并發線程會互相干擾對方的更改,從而損壞數據,或者其它線程也許不能及時看到對共享數據的更改。通過使用同步來保護對共享變量的訪問,我們可以確保線程以可預料的方式與程序變量進行交互。每個 Java 對象都可以充當鎖,synchronized 塊可以確保一次只有一個線程執行由給定鎖保護的synchronized 代碼。
    那么什么時候需要使用同步呢?
    要跨線程維護正確的可見性,只要在幾個線程之間共享非 final 變量,就必須使用 synchronized(或 volatile)以確保一個線程可以看見另一個線程做的更改。
    可見性同步的基本規則是在以下情況中必須同步:
    · 讀取上一次可能是由另一個線程寫入的變量
    · 寫入下一次可能由另一個線程讀取的變量
    許多 Java 類,包括 String、Integer 和 BigDecimal,都是不可改變的:一旦構造之后,它們的狀態就永遠不會更改。如果某個類的所有字段都被聲明成 final,那么這個類就是不可改變的。(實際上,許多不可改變的類都有非 final 字段,用于高速緩存以前計算的方法結果,如String.hashCode(),但調用者看不到這些字段。)不可改變的類使并發編程變得非常簡單。因為不能更改它們的字段,所以就不需要擔心把狀態的更
    改從一個線程傳遞到另一個線程。在正確構造了對象之后,可以把它看作是常量。
    同樣,final 字段對于線程也更友好。因為 final 字段在初始化之后,它們的值就不能更改,所以當在線程之間共享 final 字段時,不需要擔心同步訪問。
    什么時候不需要同步呢?
    在某些情況中,您不必用同步來將數據從一個線程傳遞到另一個,因為 JVM 已經隱含地為您執行同步。這些情況包括:
    · 由靜態初始化器(在靜態字段上或 static{} 塊中的初始化器)初始化數據時
    · 訪問 final 字段時
    · 在創建線程之前創建對象時
    · 線程可以看見它將要處理的對象時
    再介紹一個概念,死鎖.
    只要您擁有多個進程,而且它們要爭用對多個鎖的獨占訪問,那么就有可能發生死鎖。如果有一組進程或線程,其中每個都在等待一個只有其它進程或線程才可以執行的操作,那么就稱它們被死鎖了。
    最常見的死鎖形式是當線程 1 持有對象 A 上的鎖,而且正在等待與 B 上的鎖,而線程 2 持有對象 B 上的鎖,卻正在等待對象 A 上的鎖。這兩個線程永遠都不會獲得第二個鎖,或者釋放第一個鎖。它們只會永遠等待下去。要避免死鎖,應該確保在獲取多個鎖時,在所有的線程中都以相同的順序獲取鎖。
    同步準則
    當編寫 synchronized 塊時,有幾個簡單的準則可以遵循,這些準則在避免死鎖和性能危險的風險方面大有幫助:
    代碼塊要簡短Synchronized 塊應該簡短 — 在保證相關數據操作的完整性的同時,
    盡量簡短。把不隨線程變化的預處理和后處理移出 synchronized 塊。
    不要阻塞。不要在 synchronized 塊或方法中調用可能引起阻塞的方法,如
    則呢arInputStream.read()。
    在持有鎖的時候,不要對其它對象調用方法。這聽起來可能有些極端,但它消除了最常見的死鎖源頭。
    有關線程的編程還有很多內容,我只是介紹一個初級的入門知識,我也是才學習線程了,文章主要內容是根據網上流傳的資料改變整理.

        核心: 勇敢進取年輕的心

     


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     

    Copyright © 怎么羨慕天空的飛鳥

    主站蜘蛛池模板: 精品国产免费人成电影在线观看| 亚洲伦另类中文字幕| 免费无码AV片在线观看软件| 国产精品视_精品国产免费| 亚洲色在线无码国产精品不卡| 特级毛片全部免费播放| 岛国片在线免费观看| 永久免费精品影视网站| 免费看黄视频网站| 亚洲一区二区三区精品视频| 99久久免费国产香蕉麻豆 | 免费a级毛片大学生免费观看| 亚洲AV无码一区二区大桥未久| 91九色精品国产免费| 免费一级毛片在线播放视频免费观看永久| 午夜视频在线观看免费完整版| 亚洲一本到无码av中文字幕| 国产又大又黑又粗免费视频| 亚洲αⅴ无码乱码在线观看性色| 成人免费无码精品国产电影| 精品久久久久久久久亚洲偷窥女厕| 免费人成激情视频| 国内永久免费crm系统z在线 | 野花高清在线观看免费3中文| 日本亚洲中午字幕乱码| 免费a在线观看播放| 久久这里只精品99re免费| 日韩亚洲产在线观看| 亚洲AV网站在线观看| 少妇性饥渴无码A区免费| 亚洲视频国产精品| 免费一级毛片正在播放| 国产偷伦视频免费观看| 亚洲AV无码一区二区大桥未久| 亚洲精品无码成人片久久 | 韩国免费三片在线视频| a在线观看免费网址大全| 亚洲精品无码不卡在线播放| 久久久久久A亚洲欧洲AV冫| 久久不见久久见免费影院| 国产激情久久久久影院老熟女免费 |