1、Thread實(shí)現(xiàn)了Runnable接口,所以有兩種線程類,一是繼承Thread類,覆寫(xiě)run()方法,啟動(dòng)方式:xxThread xx=new xxThread();xx.start();; 二是實(shí)現(xiàn)runnable接口,實(shí)現(xiàn)run()方法,啟動(dòng)方式:Thread t = new Thread(new xxRunnable());t.start();。 推薦后者,將任務(wù)從線程中分離出來(lái)是比較好的設(shè)計(jì),它將任務(wù)和任務(wù)執(zhí)行分離開(kāi)來(lái)了。
2、+isAlive():boolean,測(cè)試線程當(dāng)前是否在運(yùn)行。
3、+join():void,等待線程結(jié)束。 join方法的功能就是使異步執(zhí)行的線程變成同步執(zhí)行。 t1.start(); t1.join(); System.out.PRintln(a);
4、+yield():void,使線程暫停并允許執(zhí)行其他線程。 yield()應(yīng)該做的是讓當(dāng)前運(yùn)行線程回到可運(yùn)行狀態(tài),以允許具有相同優(yōu)先級(jí)的其他線程獲得運(yùn)行機(jī)會(huì)。 因此,使用yield()的目的是讓相同優(yōu)先級(jí)的線程之間能適當(dāng)?shù)妮嗈D(zhuǎn)執(zhí)行。 但是,實(shí)際中無(wú)法保證yield()達(dá)到讓步目的,因?yàn)樽尣降木€程還有可能被線程調(diào)度程序再次選中。 yield()從未導(dǎo)致線程轉(zhuǎn)到等待/睡眠/阻塞狀態(tài)。在大多數(shù)情況下,yield()將導(dǎo)致線程從運(yùn)行狀態(tài)轉(zhuǎn)到可運(yùn)行狀態(tài),但有可能沒(méi)有效果。 在run()方法中使用 Thread.yield()。
5、synchronized 關(guān)鍵字,同步,一次只有一個(gè)線程可以訪問(wèn) 同步方法:public synchronized void deposit(){} 同步語(yǔ)句:synchronized (對(duì)象的引用){}
6、利用加鎖同步 Lock lock = new ReentrantLock();創(chuàng)建一個(gè)鎖 lock.lock(); //需要同步的代碼 finally{ lock.unlock();//放在finally中確保會(huì)被執(zhí)行 }
7、線程間協(xié)作
Condition newDeposit = lock.newCondition(); lock.lock(); while(支出>現(xiàn)存){ newDeposit.await();//當(dāng)前線程等待,直到發(fā)生某個(gè)條件 } 現(xiàn)存 - 支出 finally{ lock.unlock();}…………………………………………………
lock.lock(); 現(xiàn)存++; newDeposit.signalAll();喚醒所有等待線程 finally{ lock.unlock();}條件由Lock對(duì)象創(chuàng)建,為了調(diào)用方法(await(),signal(),signalAll()),必須首先擁有鎖。 這三個(gè)方法對(duì)應(yīng)java 5之前的wait(),notify(),notifyAll()—–Java的內(nèi)置監(jiān)聽(tīng)器 ,這些方法必須在同步方法或同步塊中調(diào)用,當(dāng)調(diào)用wait()方法時(shí),它終止線程同時(shí)釋放對(duì)象的鎖。當(dāng)線程被通知后,鎖被重新自動(dòng)獲取。
8、生產(chǎn)者和消費(fèi)者
兩個(gè)條件的鎖,notEmpty和notFull
public void write(int a){ lock.lock(); try{ while(queue.size()==CAPACITY){ notFull.await(); } queue.offer(a); notEmpty.signal(); }catch(){} finally{ lock.unlock(); } }…………………………………………
public int read(){ int value=0; lock.lock(); try{ while(queue.isEmpty){ notEmpty.await(); } value=queue.remove(); notFull.signal(); }catch(){} finally{ lock.unlock(); return value; } }9、阻塞隊(duì)列 在試圖向一個(gè)滿隊(duì)列添加元素或者從空隊(duì)列中刪除元素時(shí)會(huì)導(dǎo)致線程阻塞。 可以用阻塞隊(duì)列簡(jiǎn)化生產(chǎn)者和消費(fèi)者例子,因?yàn)橥揭言谧枞?duì)列中實(shí)現(xiàn)。
10、信號(hào)量 信號(hào)量可以用來(lái)限制訪問(wèn)共享資源的線程數(shù)。在訪問(wèn)資源前,線程必須從信號(hào)量獲取許可。 Semaphore semaphore = new Semaphore(int n);創(chuàng)建一個(gè)帶指定數(shù)目許可的信號(hào)量 semaphore.acquire();獲取許可,信號(hào)量中可用許可總量-1,如果無(wú)許可可用,線程就被鎖住直到有可用許可為止。 semaphore.release();釋放許可,信號(hào)量中可用許可總量+1。
11、死鎖
synchronized (o1) { synchronized (o2) { }}…………………………..
synchronized (o2) { synchronized (o1) { } }使用一種名為 資源排序 的簡(jiǎn)單技術(shù)可以輕易地避免死鎖的發(fā)生。
12、線程狀態(tài) 線程有5種狀態(tài),新建、就緒、運(yùn)行、阻塞或結(jié)束。 start()后線程進(jìn)入就緒狀態(tài);run()后進(jìn)入運(yùn)行狀態(tài);join()、sleep()、wait()后進(jìn)入阻塞狀態(tài); yield()進(jìn)入就緒狀態(tài);run執(zhí)行完,線程結(jié)束。 isAlive()是用來(lái)判斷線程狀態(tài)的方法,就緒、運(yùn)行和阻塞返回true;新建、結(jié)束返回false。
13、Java集合框架中的類不是線程安全的,Collections類提供六個(gè)靜態(tài)方法來(lái)將集合轉(zhuǎn)成同步版本。
14、線程同步方式
同步方法;
即有synchronized關(guān)鍵字修飾的方法。由于java的每個(gè)對(duì)象都有一個(gè)內(nèi)置鎖,當(dāng)用此關(guān)鍵字修飾方法時(shí),內(nèi)置鎖會(huì)保護(hù)整個(gè)方法。在調(diào)用該方法前,需要獲得內(nèi)置鎖,否則就處于阻塞狀態(tài)。同步代碼塊;
即有synchronized關(guān)鍵字修飾的語(yǔ)句塊。被該關(guān)鍵字修飾的語(yǔ)句塊會(huì)自動(dòng)被加上內(nèi)置鎖,從而實(shí)現(xiàn)同步。使用特殊域變量(volatile)實(shí)現(xiàn)線程同步
a.volatile關(guān)鍵字為域變量的訪問(wèn)提供了一種免鎖機(jī)制,b.使用volatile修飾域相當(dāng)于告訴虛擬機(jī)該域可能會(huì)被其他線程更新,c.因此每次使用該域就要重新計(jì)算,而不是使用寄存器中的值,d.volatile不會(huì)提供任何原子操作,它也不能用來(lái)修飾final類型的變量 。使用重入鎖實(shí)現(xiàn)線程同步;
在JavaSE5.0中新增了一個(gè)java.util.concurrent包來(lái)支持同步。ReentrantLock類是可重入、互斥、實(shí)現(xiàn)了Lock接口的鎖,它與使用synchronized方法和快具有相同的基本行為和語(yǔ)義,并且擴(kuò)展了其能力。使用局部變量實(shí)現(xiàn)線程同步;
如果使用ThreadLocal管理變量,則每一個(gè)使用該變量的線程都獲得該變量的副本,副本之間相互獨(dú)立,這樣每一個(gè)線程都可以隨意修改自己的變量副本,而不會(huì)對(duì)其他線程產(chǎn)生影響。使用阻塞隊(duì)列實(shí)現(xiàn)線程同步;
前面5種同步方式都是在底層實(shí)現(xiàn)的線程同步,但是我們?cè)趯?shí)際開(kāi)發(fā)當(dāng)中,應(yīng)當(dāng)盡量遠(yuǎn)離底層結(jié)構(gòu)。 使用javaSE5.0版本中新增的java.util.concurrent包將有助于簡(jiǎn)化開(kāi)發(fā)。LinkedBlockingQueue<E>是一個(gè)基于已連接節(jié)點(diǎn)的,范圍任意的blocking queue。 隊(duì)列是先進(jìn)先出的順序(FIFO)。使用原子變量實(shí)現(xiàn)線程同步;
需要使用線程同步的根本原因在于對(duì)普通變量的操作不是原子的。那么什么是原子操作呢?原子操作就是指將讀取變量值、修改變量值、保存變量值看成一個(gè)整體來(lái)操作即-這幾種行為要么同時(shí)完成,要么都不完成。在java的util.concurrent.atomic包中提供了創(chuàng)建了原子類型變量的工具類,使用該類可以簡(jiǎn)化線程同步。其中AtomicInteger 表可以用原子方式更新int的值,可用在應(yīng)用程序中(如以原子方式增加的計(jì)數(shù)器),但不能用于替換Integer;可擴(kuò)展Number,允許那些處理機(jī)遇數(shù)字類的工具和實(shí)用工具進(jìn)行統(tǒng)一訪問(wèn)。新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注