java 高並

1、線程與進程
進程是一個實體。每一個進程都有它自己的地址空間,一般情況下,包括文本區域(text region)、數據區域(data region)和堆棧(stack region)。文本區域存儲處理器執行的代碼;數據區域存儲變量和進程執行期間使用的動態分配的內存;堆棧區域存儲着活動過程調用的指令和本地變量。
一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的全部資源。
區別不同
a,地址空間:進程內的一個執行單元;進程至少有一個線程;它們共享進程的地址空間;而進程有自己獨立的地址空間;
b,資源擁有:進程是資源分配和擁有的單位,同一個進程內的線程共享進程的資
c,線程是處理器調度的基本單位,但進程不是.
d,二者均可併發執行.
2、 守護線程
在Java中有兩類線程:用戶線程 (User Thread)、守護線程 (Daemon Thread)。
守護線程和用戶線程的區別在於:守護線程依賴於創建它的線程,而用戶線程則不依賴。舉個簡單的例子:如果在main線程中創建了一個守護線程,當main方法運行完畢之後,守護線程也會隨着消亡。而用戶線程則不會,用戶線程會一直運行直到其運行完畢。在JVM中,像垃圾收集器線程就是守護線程。

3、java thread狀態
NEW 狀態是指線程剛創建, 尚未啓動
RUNNABLE 狀態是線程正在正常運行中, 當然可能會有某種耗時計算/IO等待的操作/CPU時間片切換等, 這個狀態下發生的等待一般是其他系統資源, 而不是鎖, Sleep等
BLOCKED 這個狀態下, 是在多個線程有同步操作的場景, 比如正在等待另一個線程的synchronized 塊的執行釋放, 也就是這裏是線程在等待進入臨界區
WAITING 這個狀態下是指線程擁有了某個鎖之後, 調用了他的wait方法, 等待其他線程/鎖擁有者調用 notify / notifyAll 一遍該線程可以繼續下一步操作, 這裏要區分 BLOCKED 和 WATING 的區別, 一個是在臨界點外面等待進入, 一個是在理解點裏面wait等待別人notify, 線程調用了join方法 join了另外的線程的時候, 也會進入WAITING狀態, 等待被他join的線程執行結束
TIMED_WAITING 這個狀態就是有限的(時間限制)的WAITING, 一般出現在調用wait(long), join(long)等情況下, 另外一個線程sleep後, 也會進入TIMED_WAITING狀態
TERMINATED 這個狀態下表示 該線程的run方法已經執行完畢了, 基本上就等於死亡了(當時如果線程被持久持有, 可能不會被回收)
4、請說出與線程同步以及線程調度相關的方法。
wait():使一個線程處於等待(阻塞)狀態,並且釋放所持有的對象的鎖;
sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方法要處理InterruptedException異常;
notify():喚醒一個處於等待狀態的線程,當然在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且與優先級無關;
notityAll():喚醒所有處於等待狀態的線程,該方法並不是將對象的鎖給所有線程,而是讓它們競爭,只有獲得鎖的線程才能進入就緒狀態;
5、進程調度算法
實時系統:FIFO(First Input First Output,先進先出算法),SJF(Shortest Job First,最短作業優先算法),SRTF(Shortest Remaining Time First,最短剩餘時間優先算法)。
交互式系統:RR(Round Robin,時間片輪轉算法),HPF(Highest Priority First,最高優先級算法),多級隊列,最短進程優先,保證調度,彩票調度,公平分享調度。

6、wait()和sleep()的區別
sleep來自Thread類,和wait來自Object類
調用sleep()方法的過程中,線程不會釋放對象鎖。而 調用 wait 方法線程會釋放對象鎖
sleep睡眠後不出讓系統資源,wait讓出系統資源其他線程可以佔用CPU
sleep(milliseconds)需要指定一個睡眠時間,時間一到會自動喚醒
7、ThreadLocal,以及死鎖分析
hreadLocal爲每個線程維護一個本地變量。
採用空間換時間,它用於線程間的數據隔離,爲每一個使用該變量的線程提供一個副本,每個線程都可以獨立地改變自己的副本,而不會和其他線程的副本衝突。
ThreadLocal類中維護一個Map,用於存儲每一個線程的變量副本,Map中元素的鍵爲線程對象,而值爲對應線程的變量副本。
徹底理解ThreadLocal

8、Synchronized 與Lock
ReentrantLock 擁有Synchronized相同的併發性和內存語義,此外還多了 鎖投票,定時鎖等候和中斷鎖等候
線程A和B都要獲取對象O的鎖定,假設A獲取了對象O鎖,B將等待A釋放對O的鎖定,
如果使用 synchronized ,如果A不釋放,B將一直等下去,不能被中斷
如果 使用ReentrantLock,如果A不釋放,可以使B在等待了足夠長的時間以後,中斷等待,而幹別的事情

ReentrantLock獲取鎖定與三種方式:
a) lock(), 如果獲取了鎖立即返回,如果別的線程持有鎖,當前線程則一直處於休眠狀態,直到獲取鎖
b) tryLock(), 如果獲取了鎖立即返回true,如果別的線程正持有鎖,立即返回false;
c)tryLock(long timeout,TimeUnit unit), 如果獲取了鎖定立即返回true,如果別的線程正持有鎖,會等待參數給定的時間,在等待的過程中,如果獲取了鎖定,就返回true,如果等待超時,返回false;
d) lockInterruptibly:如果獲取了鎖定立即返回,如果沒有獲取鎖定,當前線程處於休眠狀態,直到或者鎖定,或者當前線程被別的線程中斷

總體的結論先擺出來:

synchronized:
在資源競爭不是很激烈的情況下,偶爾會有同步的情形下,synchronized是很合適的。原因在於,編譯程序通常會儘可能的進行優化synchronized,另外可讀性非常好,不管用沒用過5.0多線程包的程序員都能理解。
ReentrantLock:
ReentrantLock提供了多樣化的同步,比如有時間限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在資源競爭不激烈的情形下,性能稍微比synchronized差點點。但是當同步非常激烈的時候,synchronized的性能一下子能下降好幾十倍。而ReentrantLock確還能維持常態。

詳解synchronized與Lock的區別與使用

9、Volatile和Synchronized
Volatile和Synchronized四個不同點:

粒度不同,前者針對變量 ,後者鎖對象和類
syn阻塞,volatile線程不阻塞
syn保證三大特性,volatile不保證原子性
syn編譯器優化,volatile不優化
要使 volatile 變量提供理想的線程安全,必須同時滿足下面兩個條件:
對變量的寫操作不依賴於當前值。
該變量沒有包含在具有其他變量的不變式中。
JAVA多線程之volatile 與 synchronized 的比較

10、CAS
CAS是樂觀鎖技術,當多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程並不會被掛起,而是被告知這次競爭中失敗,並可以再次嘗試。CAS有3個操作數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A和內存值V相同時,將內存值V修改爲B,否則什麼都不做。

11、Java中Unsafe類詳解
通過Unsafe類可以分配內存,可以釋放內存;類中提供的3個本地方法allocateMemory、reallocateMemory、freeMemory分別用於分配內存,擴充內存和釋放內存,與C語言中的3個方法對應。
可以定位對象某字段的內存位置,也可以修改對象的字段值,即使它是私有的;
掛起與恢復:將一個線程進行掛起是通過park方法實現的,調用 park後,線程將一直阻塞直到超時或者中斷等條件出現。unpark可以終止一個掛起的線程,使其恢復正常。整個併發框架中對線程的掛起操作被封裝在 LockSupport類中,LockSupport類中有各種版本pack方法,但最終都調用了Unsafe.park()方法。
cas
Java中Unsafe類詳解
12、線程池
線程池的作用:
在程序啓動的時候就創建若干線程來響應處理,它們被稱爲線程池,裏面的線程叫工作線程
第一:降低資源消耗。通過重複利用已創建的線程降低線程創建和銷燬造成的消耗。
第二:提高響應速度。當任務到達時,任務可以不需要等到線程創建就能立即執行。
第三:提高線程的可管理性。
常用線程池:ExecutorService 是主要的實現類,其中常用的有
Executors.newSingleT
hreadPool(),newFixedThreadPool(),newcachedTheadPool(),newScheduledThreadPool()。

13、ThreadPoolExecutor
構造方法參數說明
corePoolSize:核心線程數,默認情況下核心線程會一直存活,即使處於閒置狀態也不會受存keepAliveTime限制。除非將allowCoreThreadTimeOut設置爲true。
maximumPoolSize:線程池所能容納的最大線程數。超過這個數的線程將被阻塞。當任務隊列爲沒有設置大小的LinkedBlockingDeque時,這個值無效。
keepAliveTime:非核心線程的閒置超時時間,超過這個時間就會被回收。
unit:指定keepAliveTime的單位,如TimeUnit.SECONDS。當將allowCoreThreadTimeOut設置爲true時對corePoolSize生效。
workQueue:線程池中的任務隊列.
常用的有三種隊列,SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue。

threadFactory:線程工廠,提供創建新線程的功能。ThreadFactory是一個接口,只有一個方法

原理
如果當前池大小 poolSize 小於 corePoolSize ,則創建新線程執行任務。
如果當前池大小 poolSize 大於 corePoolSize ,且等待隊列未滿,則進入等待隊列
如果當前池大小 poolSize 大於 corePoolSize 且小於 maximumPoolSize ,且等待隊列已滿,則創建新線程執行任務。
如果當前池大小 poolSize 大於 corePoolSize 且大於 maximumPoolSize ,且等待隊列已滿,則調用拒絕策略來處理該任務。
線程池裏的每個線程執行完任務後不會立刻退出,而是會去檢查下等待隊列裏是否還有線程任務需要執行,如果在 keepAliveTime 裏等不到新的任務了,那麼線程就會退出。
13、Executor拒絕策略
AbortPolicy:爲java線程池默認的阻塞策略,不執行此任務,而且直接拋出一個運行時異常,切記ThreadPoolExecutor.execute需要try
catch,否則程序會直接退出.
DiscardPolicy:直接拋棄,任務不執行,空方法
DiscardOldestPolicy:從隊列裏面拋棄head的一個任務,並再次execute 此task。
CallerRunsPolicy:在調用execute的線程裏面執行此command,會阻塞入
用戶自定義拒絕策略:實現RejectedExecutionHandler,並自己定義策略模式
14、CachedThreadPool 、 FixedThreadPool、SingleThreadPool
newSingleThreadExecutor :創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務, 保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行
適用場景:任務少 ,並且不需要併發執行
newCachedThreadPool :創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程.
線程沒有任務要執行時,便處於空閒狀態,處於空閒狀態的線程並不會被立即銷燬(會被緩存住),只有當空閒時間超出一段時間(默認爲60s)後,線程池纔會銷燬該線程(相當於清除過時的緩存)。新任務到達後,線程池首先會讓被緩存住的線程(空閒狀態)去執行任務,如果沒有可用線程(無空閒線程),便會創建新的線程。
適用場景:處理任務速度 > 提交任務速度,耗時少的任務(避免無限新增線程)
newFixedThreadPool :創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
newScheduledThreadPool:創建一個定長線程池,支持定時及週期性任務執行
15、CopyOnWriteArrayList
CopyOnWriteArrayList : 寫時加鎖,當添加一個元素的時候,將原來的容器進行copy,複製出一個新的容器,然後在新的容器裏面寫,寫完之後再將原容器的引用指向新的容器,而讀的時候是讀舊容器的數據,所以可以進行併發的讀,但這是一種弱一致性的策略。
使用場景:CopyOnWriteArrayList適合使用在讀操作遠遠大於寫操作的場景裏,比如緩存。

16、AQS
AQS使用一個int成員變量來表示同步狀態,通過內置的FIFO隊列來完成獲取資源線程的排隊工作。
private volatile int state;//共享變量,使用volatile修飾保證線程可見性
1
2種同步方式:獨佔式,共享式。獨佔式如ReentrantLock,共享式如Semaphore,CountDownLatch,組合式的如ReentrantReadWriteLock
節點的狀態
CANCELLED,值爲1,表示當前的線程被取消;
SIGNAL,值爲-1,表示當前節點的後繼節點包含的線程需要運行,也就是unpark;
CONDITION,值爲-2,表示當前節點在等待condition,也就是在condition隊列中;
PROPAGATE,值爲-3,表示當前場景下後續的acquireShared能夠得以執行;
值爲0,表示當前節點在sync隊列中,等待着獲取鎖。
模板方法模式
 protected boolean tryAcquire(int arg) : 獨佔式獲取同步狀態,試着獲取,成功返回true,反之爲false
 protected boolean tryRelease(int arg) :獨佔式釋放同步狀態,等待中的其他線程此時將有機會獲取到同步狀態;
 protected int tryAcquireShared(int arg) :共享式獲取同步狀態,返回值大於等於0,代表獲取成功;反之獲取失敗;
 protected boolean tryReleaseShared(int arg) :共享式釋放同步狀態,成功爲true,失敗爲false
AQS維護一個共享資源state,通過內置的FIFO來完成獲取資源線程的排隊工作。該隊列由一個一個的Node結點組成,每個Node結點維護一個prev引用和next引用,分別指向自己的前驅和後繼結點。雙端雙向鏈表。
獨佔式:樂觀的併發策略
acquire
 a.首先tryAcquire獲取同步狀態,成功則直接返回;否則,進入下一環節;
b.線程獲取同步狀態失敗,就構造一個結點,加入同步隊列中,這個過程要保證線程安全;
 c.加入隊列中的結點線程進入自旋狀態,若是老二結點(即前驅結點爲頭結點),纔有機會嘗試去獲取同步狀態;否則,當其前驅結點的狀態爲SIGNAL,線程便可安心休息,進入阻塞狀態,直到被中斷或者被前驅結點喚醒。
release
release的同步狀態相對簡單,需要找到頭結點的後繼結點進行喚醒,若後繼結點爲空或處於CANCEL狀態,從後向前遍歷找尋一個正常的結點,喚醒其對應線程。
共享式:
共享式地獲取同步狀態.同步狀態的方法tryAcquireShared返回值爲int。
a.當返回值大於0時,表示獲取同步狀態成功,同時還有剩餘同步狀態可供其他線程獲取;
 b.當返回值等於0時,表示獲取同步狀態成功,但沒有可用同步狀態了;
 c.當返回值小於0時,表示獲取同步狀態失敗。
AQS實現公平鎖和非公平鎖
非公平鎖中,那些嘗試獲取鎖且尚未進入等待隊列的線程會和等待隊列head結點的線程發生競爭。公平鎖中,在獲取鎖時,增加了isFirst(current)判斷,當且僅當,等待隊列爲空或當前線程是等待隊列的頭結點時,纔可嘗試獲取鎖。
 Java併發包基石-AQS詳解
16、Java裏的阻塞隊列
7個阻塞隊列。分別是
ArrayBlockingQueue :一個由數組結構組成的有界阻塞隊列。
LinkedBlockingQueue :一個由鏈表結構組成的有界阻塞隊列。
PriorityBlockingQueue :一個支持優先級排序的無界阻塞隊列。
DelayQueue:一個使用優先級隊列實現的無界阻塞隊列。
SynchronousQueue:一個不存儲元素的阻塞隊列。
LinkedTransferQueue:一個由鏈表結構組成的無界阻塞隊列。
LinkedBlockingDeque:一個由鏈表結構組成的雙向阻塞隊列。

添加元素
Java中的阻塞隊列接口BlockingQueue繼承自Queue接口。BlockingQueue接口提供了3個添加元素方法。
add:添加元素到隊列裏,添加成功返回true,由於容量滿了添加失敗會拋出IllegalStateException異常
offer:添加元素到隊列裏,添加成功返回true,添加失敗返回false
put:添加元素到隊列裏,如果容量滿了會阻塞直到容量不滿

刪除方法
3個刪除方法
poll:刪除隊列頭部元素,如果隊列爲空,返回null。否則返回元素。
remove:基於對象找到對應的元素,並刪除。刪除成功返回true,否則返回false
take:刪除隊列頭部元素,如果隊列爲空,一直阻塞到隊列有元素並刪除

17、condition
對Condition的源碼理解,主要就是理解等待隊列,等待隊列可以類比同步隊列,而且等待隊列比同步隊列要簡單,因爲等待隊列是單向隊列,同步隊列是雙向隊列。

java condition使用及分

18、DelayQueue
隊列中每個元素都有個過期時間,並且隊列是個優先級隊列,當從隊列獲取元素時候,只有過期元素纔會出隊列。

併發隊列-無界阻塞延遲隊列delayqueue原理探究

19、Fork/Join框架
 Fork/Join框架是Java 7提供的一個用於並行執行任務的框架,是一個把大任務分割成若干個小任務,最終彙總每個小任務結果後得到大任務結果的框架。Fork/Join框架要完成兩件事情:

  1.任務分割:首先Fork/Join框架需要把大的任務分割成足夠小的子任務,如果子任務比較大的話還要對子任務進行繼續分割

  2.執行任務併合並結果:分割的子任務分別放到雙端隊列裏,然後幾個啓動線程分別從雙端隊列裏獲取任務執行。子任務執行完的結果都放在另外一個隊列裏,啓動一個線程從隊列裏取數據,然後合併這些數據。

  在Java的Fork/Join框架中,使用兩個類完成上述操作

  1.ForkJoinTask:我們要使用Fork/Join框架,首先需要創建一個ForkJoin任務。該類提供了在任務中執行fork和join的機制。通常情況下我們不需要直接集成ForkJoinTask類,只需要繼承它的子類,Fork/Join框架提供了兩個子類:

    a.RecursiveAction:用於沒有返回結果的任務

    b.RecursiveTask:用於有返回結果的任務

  2.ForkJoinPool:ForkJoinTask需要通過ForkJoinPool來執行

  任務分割出的子任務會添加到當前工作線程所維護的雙端隊列中,進入隊列的頭部。當一個工作線程的隊列裏暫時沒有任務時,它會隨機從其他工作線程的隊列的尾部獲取一個任務(工作竊取算法)。
Fork/Join框架的實現原理
  ForkJoinPool由ForkJoinTask數組和ForkJoinWorkerThread數組組成,ForkJoinTask數組負責將存放程序提交給ForkJoinPool,而ForkJoinWorkerThread負責執行這

20、原子操作類
在java.util.concurrent.atomic包下,可以分爲四種類型的原子更新類:原子更新基本類型、原子更新數組類型、原子更新引用和原子更新屬性。

原子更新基本類型
使用原子方式更新基本類型,共包括3個類:
AtomicBoolean:原子更新布爾變量
AtomicInteger:原子更新整型變量
AtomicLong:原子更新長整型變量
原子更新數組
通過原子更新數組裏的某個元素,共有3個類:
AtomicIntegerArray:原子更新整型數組的某個元素
AtomicLongArray:原子更新長整型數組的某個元素
AtomicReferenceArray:原子更新引用類型數組的某個元素
AtomicIntegerArray常用的方法有:
int addAndSet(int i, int delta):以原子方式將輸入值與數組中索引爲i的元素相加
boolean compareAndSet(int i, int expect, int update):如果當前值等於預期值,則以原子方式更新數組中索引爲i的值爲update值
原子更新引用類型
AtomicReference:原子更新引用類型
AtomicReferenceFieldUpdater:原子更新引用類型裏的字段
AtomicMarkableReference:原子更新帶有標記位的引用類型。
原子更新字段類
如果需要原子更新某個類的某個字段,就需要用到原子更新字段類,可以使用以下幾個類:
AtomicIntegerFieldUpdater:原子更新整型字段
AtomicLongFieldUpdater:原子更新長整型字段
AtomicStampedReference:原子更新帶有版本號的引用類型。
要想原子更新字段,需要兩個步驟:
每次必須使用newUpdater創建一個更新器,並且需要設置想要更新的類的字段
更新類的字段(屬性)必須爲public volatile
21、同步屏障CyclicBarrier
CyclicBarrier 的字面意思是可循環使用(Cyclic)的屏障(Barrier)。它要做的事情是,讓一組線程到達一個屏障(也可以叫同步點)時被阻塞,直到最後一個線程到達屏障時,屏障纔會開門,所有被屏障攔截的線程纔會繼續幹活。CyclicBarrier默認的構造方法是CyclicBarrier(int parties),其參數表示屏障攔截的線程數量,每個線程調用await方法告訴CyclicBarrier我已經到達了屏障,然後當前線程被阻塞。
CyclicBarrier和CountDownLatch的區別

CountDownLatch的計數器只能使用一次。而CyclicBarrier的計數器可以使用reset() 方法重置。所以CyclicBarrier能處理更爲複雜的業務場景,比如如果計算髮生錯誤,可以重置計數器,並讓線程們重新執行一次。
CyclicBarrier還提供其他有用的方法,比如getNumberWaiting方法可以獲得CyclicBarrier阻塞的線程數量。isBroken方法用來知道阻塞的線程是否被中斷。比如以下代碼執行完之後會返回true。

22、Semaphore
Semaphore(信號量)是用來控制同時訪問特定資源的線程數量,它通過協調各個線程,以保證合理的使用公共資源
Semaphore可以用於做流量控制,特別公用資源有限的應用場景,比如數據庫連接。假如有一個需求,要讀取幾萬個文件的數據,因爲都是IO密集型任務,我們可以啓動幾十個線程併發的讀取,但是如果讀到內存後,還需要存儲到數據庫中,而數據庫的連接數只有10個,這時我們必須控制只有十個線程同時獲取數據庫連接保存數據,否則會報錯無法獲取數據庫連接。這個時候,我們就可以使用Semaphore來做流控,代碼如下:

控制併發線程數的Semaphore

23、死鎖,以及解決死鎖
死鎖產生的四個必要條件
互斥條件:資源是獨佔的且排他使用,進程互斥使用資源,即任意時刻一個資源只能給一個進程使用,其他進程若申請一個資源,而該資源被另一進程佔有時,則申請者等待直到資源被佔有者釋放。
不可剝奪條件:進程所獲得的資源在未使用完畢之前,不被其他進程強行剝奪,而只能由獲得該資源的進程資源釋放。
請求和保持條件:進程每次申請它所需要的一部分資源,在申請新的資源的同時,繼續佔用已分配到的資源。
循環等待條件:在發生死鎖時必然存在一個進程等待隊列{P1,P2,…,Pn},其中P1等待P2佔有的資源,P2等待P3佔有的資源,…,Pn等待P1佔有的資源,形成一個進程等待環路,環路中每一個進程所佔有的資源同時被另一個申請,也就是前一個進程佔有後一個進程所深情地資源。

解決死鎖
一是死鎖預防,就是不讓上面的四個條件同時成立。
二是,合理分配資源。
三是使用銀行家算法,如果該進程請求的資源操作系統剩餘量可以滿足,那麼就分配。

24、進程間的通信方式
管道( pipe):管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關係的進程間使用。進程的親緣關係通常是指父子進程關係。
有名管道 (named pipe) : 有名管道也是半雙工的通信方式,但是它允許無親緣關係進程間的通信。
信號量( semophore ) : 信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。它常作爲一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作爲進程間以及同一進程內不同線程之間的同步手段。
消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩衝區大小受限等缺點。
信號 ( sinal ) : 信號是一種比較複雜的通信方式,用於通知接收進程某個事件已經發生。
共享內存( shared memory ) :共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的 IPC 方式,它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號量,配合使用,來實現進程間的同步和通信。
套接字( socket ) : 套解口也是一種進程間通信機制,與其他通信機制不同的是,它可用於不同機器間的進程通信。
中斷
interrupt()的作用是中斷本線程。
本線程中斷自己是被允許的;其它線程調用本線程的interrupt()方法時,會通過checkAccess()檢查權限。這有可能拋出SecurityException異常。
如果本線程是處於阻塞狀態:調用線程的wait(), wait(long)或wait(long, int)會讓它進入等待(阻塞)狀態,或者調用線程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也會讓它進入阻塞狀態。若線程在阻塞狀態時,調用了它的interrupt()方法,那麼它的“中斷狀態”會被清除並且會收到一個InterruptedException異常。例如,線程通過wait()進入阻塞狀態,此時通過interrupt()中斷該線程;調用interrupt()會立即將線程的中斷標記設爲“true”,但是由於線程處於阻塞狀態,所以該“中斷標記”會立即被清除爲“false”,同時,會產生一個InterruptedException的異常。
如果線程被阻塞在一個Selector選擇器中,那麼通過interrupt()中斷它時;線程的中斷標記會被設置爲true,並且它會立即從選擇操作中返回。
如果不屬於前面所說的情況,那麼通過interrupt()中斷線程時,它的中斷標記會被設置爲“true”。
中斷一個“已終止的線程”不會產生任何操作。

終止處於“阻塞狀態”的線程
通常,我們通過“中斷”方式終止處於“阻塞狀態”的線程。
當線程由於被調用了sleep(), wait(), join()等方法而進入阻塞狀態;若此時調用線程的interrupt()將線程的中斷標記設爲true。由於處於阻塞狀態,中斷標記會被清除,同時產生一個InterruptedException異常。將InterruptedException放在適當的爲止就能終止線程,
終止處於“運行狀態”的線程
interrupted() 和 isInterrupted()的區別
最後談談 interrupted() 和 isInterrupted()。
interrupted() 和 isInterrupted()都能夠用於檢測對象的“中斷標記”。
區別是,interrupted()除了返回中斷標記之外,它還會清除中斷標記(即將中斷標記設爲false);而isInterrupted()僅僅返回中斷標記。
interrupt()和線程終止方式
 

發佈了32 篇原創文章 · 獲贊 52 · 訪問量 44萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章