VOOZH about

URL: https://read01.com/Q6aOA7.html

⇱ java線程基礎 - 壹讀


Sunday, Apr 12, 2026

java線程基礎

2016/08/09 來源:CSDN博客
Java(3)

版權聲明:本文為博主原創文章,未經博主允許不得轉載。

在java中,每個任務都是Runnable接口的一個實例,也可以成為運行對象。線程上本質上講就是便於任務執行的對象。

任務就是對象。

創建一個線程1:實現Runnable接口

  • 創建一個任務
TaskClass task = new TaskClass(...);
  • 任務類必須在線程中執行
Threadthread=newThread(task);
  • 然後調用start方法告訴虛擬機該線程準備運行
thread.start;

TaskClass是自己創建的,完成要完成的任務。」=」左邊的Taskclass可以換成Runnable。TaskClass實現Runnable接口。

創建一個線程2:繼承Thread類

  • 創建Thread類擴展對象
thread.start;

這裡的TaskClass和上面的區別是:這裡是繼承了Thread類,其餘都一樣。Thread類本身實現了Runnable接口。

任務類(這裡是實現Runnable接口的任務類)

  • 任務類比普通類多了run方法。具體如下:
public void run(...) { ... }
  • 任務類要實現Runnable接口
classTaskClassimplementsRunnable { ... }

直接調用任務類中run方法,只是在同一個線程中執行該方法,而沒有新的線程被啟動。

Thread 類

  • Thread類包含stop,suspend和resume方法,普遍認為不安全,不使用
  • 代替stop方法,可以給Thread類賦值null,來表明停止。
  • yield的方法為其他線程臨時讓出cpu時間
  • sleep(long mills)
    設置休眠,讓出cpu時間,單位毫秒。
  • java線程優先級1-10.
    • MIN_PRIORITY = 1
    • NORM_PRIORITY = 5
    • MAX_PRIORITY = 10

    如果總有一個較高的優先級在運行,或者相同的優先級線程不退出,那麼這個線程可能永遠沒有運行機會。這種情況稱為資源競爭或缺乏狀態(contention or starvation)。為了避免競爭,高優先級線程必須定時調用yield方法或sleep方法。
線程池
  • 線程池是管理並發執行任務的理想方法。Java提供Executor接口來執行線程池中的任務。ExecutorService來管理和控制任務。

執行創建3個線程來並發執行3個任務

ExecutorService executor = Executors.newFixedThreadPool(3); executor.execute(printA); executor.execute(thread1); executor.execute(print100); executor.shutdown;
  • Executors.newFixedThreadPool(3):

    將3改為1,這3個任務將順序執行

    改為Executors.newCachedThreadPool,則為每>>個等待的任務創建一個新線程,即來一個任務,創建一個線程,所以,任務會並發的執行。
    shutdown通知執行器關閉,不能接收新任務。但現有任務將繼續執行直到完成。


線程同步
為避免競爭狀態,應該防止多個線程同時進入程序的某一特定部分,程序中的這部分稱為臨界區(critical region)。 解決辦法 - 添加關鍵字synchroized,下面兩種方法都行。publicsynchronizedvoidxMethod { //thod body } publicvoidxMethod { synchronized(this) { //method body } }同步(synhronized)方法在執行之前都隱式的加了鎖。
  • (顯式)加鎖。
    • 實例方法:給調用該方法的對象加鎖
    • 靜態方法:要給這個類加鎖

private static Account account = new Account; lock.lock; try { ... } catch (InterruptedException ex) { } finally { lock.unlock; }線程間協作
  • await:讓當前的線程都處於等待狀態,直到條件發生
  • signal:喚醒一個等待的線程
  • signalAll:喚醒所有等待的線程
privatestatic Condition newDeposit = lock.newCondition; newDeposit.await; newDeposit.signalAll;java的內置監視器(java5 之前的內容) 一旦一個線程鎖住對象,該對象就成為監視器。 用法:在方法或塊上使用關鍵字synchronized. wait,notify,或notifyAll方法在接收對象的同步方法或同步塊調用。synchronized (anObject) { ... anObject.wait; ... } synchronized (anObject) { ... anObject.notify; ... }阻塞隊列(blocking queue) 阻塞隊列在試圖向一個滿隊列添加元素或者空隊列刪除元素時,會導致線程阻塞。 java支持3個具體的阻塞隊列
  • ArrayBlockingQueue :可選的容量ArrayBlockingQueue(capacity:int)或者指定公平性ArrayBlockingQueue(capacity:int,fair:boolea)
  • LinkedBlockingQueue 可以創建不受限的LinkedBlockingQueue或者受限的隊列LinkedBlockingQueue(capacity:int)
  • PriorityBlockingQueue可以創建不受限的PriorityBlockingQueue或者受限的隊列PriorityBlockingQueue(capacity:int)
  • put 向尾添加元素
  • take 向頭刪除元素

信號量

信號量可以用來限制訪問共享資源的線程數,在訪問資源之前,線程必須從信號量獲取許可。在訪問完資源之後,這個線程必須將資源返回給信號量。

  • 創建許可
privatestatic Semephore semaphore = new Semaphore(n);
  • 從信號量獲取許可(不可用,等待)
semaphore.acquire;
  • 釋放對信號源的許可
semaphore.release;

感覺信號量和鎖是類似的,獲得許可相當於上鎖,上鎖只允許一個資源使用,獲得許可後,只允許有限的線程進行訪問資源。

避免死鎖

有時兩個或者多個線程需要在幾個共享的對象上獲取鎖,這可能會導致死鎖。

資源排序(resource ordering)可以輕易避免死鎖的發生。假如線程要想對資源2上鎖,必須要先獲取資源1的鎖。

線程的狀態

  • 新建(New):創建新的線程
  • 就緒(Ready):start 或超時(cpu分配的時間用完)或yield
  • 運行(Running):run
  • 阻塞(Blocked):join(等待目標結束中。。),sleep(等待超時中。。。),wait等待通知中。。當阻塞的行為不起作用時,線程就被重新激活進入就緒狀態。
  • 結束(finished):run完成

就緒和運行線程是激活的。新建,阻塞和結束線程沒被激活。

同步集合

Java集合框架中的類不是線程安全的,也就是說,如果它們同時被多個線程訪問和更新,它們的內容可能被破壞。

java有6中靜態方法將集合轉換為同步版本,稱為同步包裝類。

  • syncoronizedCollection(c:Collection):Collection
  • syncoronizedList(list:List):List
  • syncoronizedMap(map:Map):Map
  • syncoronizedSet(set:Set):Set 規則集
  • syncoronizedSortedMap(s:SortedMap):SortedMap 有序圖
  • syncoronizedSortedSet(s:SortedSet):SortedSet 有序規則集

java.util.Vector java.util.Stack java.util.HashTable中的方法已經被同步,這些都是java中的舊類。java.util.ArrayList,java.util.LinkedList,java.util.Map是對應的新類。

同步包裝類都是線程安全的,但是疊代器具有快速失敗的特性:如果整個集合使用一個疊代器,疊代器通常拋出異常。為了避免這個錯誤,需要創建一個同步集合對象,並且在遍歷它時,獲取對象上的鎖。

Set hashSet = Collections.synchronizedSet(new HshSet); synchronized (hashSet) { Iterator iterator = hashSet.iterator; while(iterator.hasNext) { System.out.println(iterator.next); } }
您可能感興趣
免責聲明:本文內容來源于CSDN博客,文章觀點不代表壹讀立場,如若侵犯到您的權益,或涉不實謠言,敬請向我們提出檢舉
最新文章 / 服務條款 / 私隱保護 / DMCA / 聯絡我們

壹讀/READ01.COM