線程阻塞工具類 :LockSupport
- LockSupport 是一個(gè)非常實(shí)用的線程阻塞工具神年, 可以在線程內(nèi)任意位置闰蛔,讓線程阻塞。 這個(gè)類補(bǔ)充了 使用resume 導(dǎo)致線程無法繼續(xù)執(zhí)行的情況,和wait方法相比 ,不需要獲得某個(gè)對(duì)象的鎖 耻涛,也不會(huì)拋出 中斷異常。
public class LockSupportDemo {
public static Object U = new Object() ;
static ChangeObjectThread t1 = new ChangeObjectThread("t1");
static ChangeObjectThread t2 = new ChangeObjectThread("t2");
public static class ChangeObjectThread extends Thread{
public ChangeObjectThread (String name){
super.setName(name);
}
@Override
public void run() {
synchronized(U){
System.out.println("in " + getName());
LockSupport.park();
}
}
}
public static void main(String[] args) throws Exception {
t1.start();
Thread.sleep(100);
t2.start();
LockSupport.unpark(t1);
LockSupport.unpark(t2);
t1.join();
t2.join();
}
}
- 在該代碼中瘟檩,我們使用的是方法park(),和unpark(); 該類為每個(gè)線程準(zhǔn)備了一個(gè)許可抹缕, 如果許可可用,那么park()函數(shù)就會(huì)立即返回墨辛,消費(fèi)掉這個(gè)許可卓研,。 如果許可不可用睹簇,就會(huì)發(fā)生阻塞奏赘。這個(gè)優(yōu)點(diǎn)是即使 unpark ()發(fā)生在park上 ,也能順利的保證park操作正確執(zhí)行带膀。
- 除了有定時(shí)阻塞的功能之外志珍, park()還支持 中斷影響,但是與其他中斷函數(shù)不一樣橙垢,park()函數(shù) 不會(huì)拋出中斷異常垛叨, 只是默默返回。 但是我們可以用 Thread.interupted() 等方法獲得中斷標(biāo)記柜某。代碼演示如下......
public class LockSupportIntDemo {
public static Object U = new Object() ;
static ChangeObjectThread t1 = new ChangeObjectThread("t1");
static ChangeObjectThread t2 = new ChangeObjectThread("t2");
public static class ChangeObjectThread extends Thread{
public ChangeObjectThread (String name){
super.setName(name);
}
@Override
public void run() {
synchronized(U){
System.out.println("in " + getName());
LockSupport.park();
if(Thread.interrupted()){
System.out.println(getName() + "被中斷了");
}
}
System.out.println(getName() + "執(zhí)行結(jié)束了");
}
}
public static void main(String[] args) throws Exception {
t1.start();
Thread.sleep(100);
t2.start();
t1.interrupt();
LockSupport.unpark(t2);
}
}
線程復(fù)用:線程池
- 線程池是為了方便我們對(duì)創(chuàng)建的線程進(jìn)行復(fù)用嗽元。節(jié)約了創(chuàng)建和銷毀對(duì)象的時(shí)間。
jdk 對(duì)線程池的使用喂击。
- jdk 提供了一套Executor 框架剂癌, 本質(zhì)就是線程池的使用。
- 從圖中可以看到ThreadPoolExecutor 表示一個(gè)線程池翰绊, Executors 類則扮演者線程池工廠的角色佩谷。 通過Executors 可以獲得擁有特定功能的線程池旁壮。 我們?cè)趗ml圖上 ,可以看到Executor 接口 谐檀,我們通過該接口 讓Runnable 的對(duì)象可以被ThreadPoolExecutor 線程池調(diào)度抡谐。
- Executor 框架提供了各種類型線程池。工廠方法如下:
- newFixedThreadPool(int nThreads); 該方法返回的是一個(gè)固定線程數(shù)量的線程池桐猬,該線程池的線程數(shù)量始終不變麦撵。 當(dāng)有新任務(wù)提交過來的時(shí)候 ,線程池中有空閑線程溃肪,則立即執(zhí)行免胃。若沒有 ,則會(huì)把新的任務(wù)放到一個(gè)隊(duì)列中惫撰。等待有空閑線程的時(shí)候就會(huì)執(zhí)行隊(duì)列中的任務(wù)羔沙。
- newSingleThreadExecutor(): 方法會(huì)返回一個(gè)只有一個(gè)線程的線程池。若多余一個(gè)任務(wù)被提交到該線程池厨钻。任務(wù)同樣會(huì)保存在任務(wù)隊(duì)列中撬碟,等待線程空閑,按照先入先出的順序 執(zhí)行隊(duì)列中的任務(wù)莉撇。
- newCachedThreadPool() 方法: 方法會(huì)返回一個(gè)根據(jù)實(shí)際情況調(diào)整線程數(shù)量的線程池呢蛤。線程池的里面的線程數(shù)量不確定。在任務(wù)提交過來的時(shí)候棍郎,若有空閑線程 則直接復(fù)用空閑線程其障,若所有線程都在使用,那么會(huì)創(chuàng)建新的線程處理任務(wù)涂佃。所有線程結(jié)束后励翼,將返回線程池進(jìn)行復(fù)用。
- newSingThreadScheduleExecutor(): 該方法會(huì)返回一個(gè)ScheduledExecutorService對(duì)象辜荠,線程池大小為1汽抚, 這個(gè)線程池是在給定任務(wù)時(shí)間執(zhí)行某任務(wù)的功能,或者是周期性執(zhí)行任務(wù)
- newSheduledThreadPool(): 方法會(huì)返回ScheduledExecutorService對(duì)象伯病,該線程池可以指定線程數(shù)量造烁。
- 對(duì)計(jì)劃任務(wù)線程池的使用:newSheduledThreadPool():
- 主要方法如下 對(duì)該線程里面的設(shè)置。
/**下面兩種方法 會(huì)在給定時(shí)間進(jìn)行一次任務(wù)調(diào)度午笛。**/
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);
/*** 該方法是對(duì)任務(wù)周期性的調(diào)度 fixRate 是任務(wù)調(diào)度頻率是一致的**/
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
/***同樣 周期性的調(diào)度 FixedDelay 是在任務(wù)完成一周周期后 再經(jīng)過某個(gè)時(shí)間長度 才會(huì)執(zhí)行任務(wù)**/
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,
long delay, TimeUnit unit);
//代碼演示如下:
public class ScheduledExecutorServiceDemo {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(System.currentTimeMillis() / 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}, 0, 2, TimeUnit.SECONDS);
}
}
- 還有一種情況如果任務(wù)執(zhí)行時(shí)間超過我們所規(guī)定的時(shí)間 惭蟋,會(huì)怎么樣,是聚集還是药磺? 答案就是 會(huì)持續(xù)的當(dāng)當(dāng)前任務(wù)執(zhí)行完成后立即執(zhí)行下面的任務(wù)告组,。還有一個(gè)如果任務(wù)出現(xiàn)異常癌佩,那么該任務(wù)會(huì)被中斷 后續(xù)的任務(wù)也會(huì)被中斷木缝,那么需要我們最好異常處理便锨。
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者