七、多線程

一、線程概述

線程是在程序中獨立并發(fā)的執(zhí)行流,相比于進程,線程具有更高的性能,多個線程可以共享一個進程虛擬空間,線程之間共享內存非常方便,可以擁有很高的并發(fā)。

二、線程的創(chuàng)建和啟動

2.1 繼承Thread類創(chuàng)建線程類

通過繼承Thread類來創(chuàng)建啟動多線程的步驟如下:
(1)定義Thread的子類,重寫run方法
(2)創(chuàng)建Thread子類的實例
(3)通過start來啟動線程
Thread.currentThread()可以返回當前正在執(zhí)行的線程對象
getName()可以返回線程的名字

public class FirstThread extends Thread{
    public void run()
    {...}
}
new FirstThread().start();

2.2 實現(xiàn)Runnable接口創(chuàng)建線程類

通過Runnable接口來創(chuàng)建并啟動多線程的步驟如下:
(1)定義Runnable的實現(xiàn)類,并且重寫run方法
(2)創(chuàng)建Runnable實現(xiàn)類的實例,并且以此實例作為Thread的target來創(chuàng)建Thread對象

public class SecondThread implements Runnable
{
    public void run()
    {...}
}
new Thread(st,'name').start();

采用Runnable接口的方式來創(chuàng)建的多條線程可以共享線程類的實例屬性。
采用Runnable接口方式來創(chuàng)建的線程只能通過Thread.currentThread()來獲取當前線程,而不能通過this

3 線程的生命周期

  • 新建狀態(tài):new了一個線程之后
  • 就緒狀態(tài):調用了start之后(永遠不要直接調用run方法)
  • 運行狀態(tài):線程獲得CPU,開始運行run方法之后
  • 阻塞狀態(tài):調用sleep,調用阻塞式IO方法,等待通知,程序調用了suspend方法等,都會使線程進入阻塞狀態(tài)。
  • 線程死亡:run()執(zhí)行完畢,拋出未捕獲的Exception和Error,或者調用該程序的stop()方法來結束該線程。

可以通過線程的isAlive方法來判斷線程是否死亡
不要試圖對一個已經死亡的線程調用start方法

4 控制線程

4.1 join線程

某個線程調用另一個線程的join方法以后,該線程將被阻塞,直到被join的線程執(zhí)行完畢以后為止。

  • join()
  • join(long millis)
  • join(long millis,int nanos)

4.2 后臺線程

后臺線程有個特征:如果前臺線程都死亡,則后臺線程會自動死亡。
通過調用Thread的setDaemon(true)的時候,就可以將其設為后臺線程。
可以通過isDaemon()來判斷是否是后臺線程

4.3 線程睡眠Sleep

  • Thread.sleep(long millis)
  • Thread.sleep(long millis, int nanos)

4.4 線程讓步y(tǒng)ield

yield方法不會阻塞該線程,而是轉入就緒狀態(tài),讓線程調度器重新調度一次。

  • Thread.yield

4.5 改變線程優(yōu)先級

  • Thread.setPriority(int newPriority)
    優(yōu)先級值在1~10之間,也可以使用MAX_PRIORITY(10),MIN_PRIORITY(1),NORM_PRIORITY(5)

5 線程的同步

5.1同步代碼塊

synchronized(obj){ 同步代碼塊 }

5.2同步方法

public synchronized void draw(double drawAmount)

5.3釋放同步監(jiān)視器的鎖定

以下情況會釋放:

  • 代碼塊執(zhí)行完畢
  • break return
  • 拋出錯誤或者異常
  • 程序執(zhí)行了同步監(jiān)視器對象的wait()方法

5.4 同步鎖

常用的有可重用鎖ReentrantLock,可重用的意思是說,對已經加鎖的ReentrantLock可以再次上鎖,該對象會維持一個計數器來記錄。

public class Accout
{
    private final ReetrantLock lock = new ReentrantLock();
    public void draw(double drawAmout)
    {
        lock.lock();
        try
        {
        //臨界區(qū)
        }
        finally
        {
            lock.unlock();
        }
    }
}

5.5 死鎖

當兩個線程相互等待對方釋放同步監(jiān)視器就會發(fā)生死鎖。

6 線程通信

6.1 線程的協(xié)調運行

Object類提供的wait(), notify(),notifyAll()三個方法,必須由同步監(jiān)視器來調用:

  • 對于使用synchronized修飾的同步方法,該類的默認實例this就是同步監(jiān)視器
  • 對于使用synchronized修飾的代碼塊,后面括號里的對象就是同步監(jiān)視器

6.2 使用條件變量進行控制協(xié)調

如果程序不使用synchronized關鍵字來保持同步,而是直接使用Lock對象來保持同步,則系統(tǒng)中不存在隱式的同步監(jiān)視器對象。Java提供了一個Condition類來保持協(xié)調。

  • await()
  • signal()
  • signalAll()
public class Account
{
    private final Lock lock = new ReentrantLock();
    private final Condition cond = lock.newCondition();

####6.3 使用管道流
如果兩條線程之間需要更多的信息交互,則可以考慮使用管道流。

PipedWriter pw = null;
PipedReader pr = null;
try
{
pw = new PipedWriter();
pr = new PipedReader();
pw.connect(pr);
new WriterThread(pw).start();
new ReaderThread(pr).start();
}

###7 Callable和Future
Callable看起來像是Runnable的接口和增強版,call方法是其線程執(zhí)行體,但是比run()方法更強大:可以有返回值,可以拋出異常

class RtnThread implements Callable<Integer>
{
public Integer call(){
return i
}
}
public class CallableTest
{
public static void main(String[] args)
{
RtnThread rt = new RtnThread();
FutrueTask<Integer> task = new FutureTask<Integer>(rt);
new Thread(task,'name').start();
System.out.println(task.get());
}
}


###8 線程池
略過

###9 線程相關類
####9.1 ThreadLocal類
ThreadLocal類是線程局部變量的意思,就是為每一個使用該變量的線程都提供一個變量值的副本。從而避免沖突。
ThreadLocal提供了三個public方法:
* T get()
* void remove()
* void set(T value)
>如果需要進行多個線程之間的資源共享,就需要使用同步機制,如果只是需要隔離多個線程之間的共享沖突,則可以使用ThreadLocal

####9.2 線程包裝不安全的集合
Java集合中介紹的ArrayList,LinkedList, HashSet, TreeSet, HashMap都是線性不安全的。可以使用Collections的方法來將其變成線程安全:
SynchronizedCollection/List/Map/Set/SortedMap/SortedSet

####9.3 線程安全的集合類
JDK1.5開始,java.util.concurrent包下提供了ConcurrentHashMap, ConcurrentLinkedQueue。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容