Java創(chuàng)建多線程的四種方式
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
? 作者?|??孤獨(dú)患者的病態(tài)
來(lái)源 |? urlify.cn/N3Ifuy
66套java從入門到精通實(shí)戰(zhàn)課程分享
在進(jìn)行講解線程的創(chuàng)建方式之前,首先了解下什么是進(jìn)程,什么是線程,進(jìn)程與線程之間的關(guān)系等
什么是進(jìn)程?
其實(shí)當(dāng)一個(gè)程序進(jìn)入內(nèi)存運(yùn)行時(shí),就是一個(gè)進(jìn)程,進(jìn)程是處于運(yùn)行中的程序,并且具有一定的獨(dú)立功能,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位,具有獨(dú)立性,動(dòng)態(tài)性,并發(fā)性,這里的獨(dú)立性指的是在系統(tǒng)中獨(dú)立存在,有獨(dú)立資源,有獨(dú)立地址空間,沒(méi)有進(jìn)程允許,不會(huì)跟別的進(jìn)程交互;動(dòng)態(tài)性指的是進(jìn)程在系統(tǒng)中有生命周期以及各種不同的狀態(tài),這也是跟程序的區(qū)別,進(jìn)程加入了時(shí)間的概念;并發(fā)性指的是進(jìn)程間可以在單處理器上并發(fā)執(zhí)行,獨(dú)立互不影響
那什么是線程呢?
多線程其實(shí)就是擴(kuò)展了多進(jìn)程的概念,使一個(gè)進(jìn)程可以同時(shí)并發(fā)處理多個(gè)任務(wù),可以看成是輕量級(jí)的進(jìn)程;線程是進(jìn)程的組成部分,一個(gè)進(jìn)程可以有多個(gè)線程,線程可以有自己的堆棧,程序計(jì)數(shù)器,局部變量,但是沒(méi)有系統(tǒng)資源,線程是必須有一個(gè)父進(jìn)程的,他與父進(jìn)程的其他線程是共享全部資源,線程的調(diào)度與管理是由父進(jìn)程負(fù)責(zé)為完成
簡(jiǎn)單來(lái)說(shuō)就是,操作系統(tǒng)可以同時(shí)執(zhí)行多個(gè)任務(wù),每個(gè)任務(wù)就是進(jìn)程,進(jìn)程可以同時(shí)執(zhí)行多個(gè)任務(wù),每個(gè)任務(wù)就是線程
如何創(chuàng)建多線程?
創(chuàng)建多線程的方式可以概括為四種:
1,繼承Thread類,重寫run()方法
2,實(shí)現(xiàn)Runnable接口,重寫run()方法
3,實(shí)現(xiàn)Callable接口, 重寫call()方法,借助Future執(zhí)行
4,借助Executor框架使用線程池創(chuàng)建線程
具體線程創(chuàng)建方式如下:
一:繼承Thread類創(chuàng)建線程
class?MyThead?extends??Thread?{
????@Override
????public?void?run()?{
????????System.out.println(Thread.currentThread().getName()?+?":?繼承Thread線程啦");
????}
}
調(diào)用線層的start()方法啟動(dòng)線程
new?MyThead().start();
執(zhí)行結(jié)果如下:
?
?注:Thread其實(shí)也是實(shí)現(xiàn)了Runnable接口
二:實(shí)現(xiàn)Runnable接口創(chuàng)建線程
class?MyRunnable?implements??Runnable?{
????public?void?run()?{
????????System.out.println(Thread.currentThread().getName()?+?":?實(shí)現(xiàn)Runnable線程啦");
????}
}
? 借助Thread類調(diào)用線層的start()方法啟動(dòng)線程
new?Thread(new?MyRunnable())?.start();
執(zhí)行結(jié)果如下:
![]()
三:使用Callable和Future接口創(chuàng)建線程
Java5開(kāi)始提供Callable接口,提供call方法作為線程的執(zhí)行體,可以看成是Runnable接口的增強(qiáng)版本,增強(qiáng)點(diǎn)在于call()方法可以有返回值,并且可以拋出異常,由于Callable是新增的接口,不能作為Thread的target使用,所以Java5里提供了Future接口,該接口實(shí)現(xiàn)了Runnable,F(xiàn)uture的實(shí)現(xiàn)類FutureTask類用來(lái)包裝Callable對(duì)象,那么該怎么調(diào)用并獲取返回值呢?下面用代碼進(jìn)行展示用法:
創(chuàng)建Callable對(duì)象
class?MyCallable??implements?Callable啟動(dòng)線程
public?static?void?main(String[]?args)?{
????????FutureTask執(zhí)行結(jié)果如下:
?
四:借助Executor框架使用線程池創(chuàng)建線程
?Executors提供了一系列工廠方法用于創(chuàng)先線程池,創(chuàng)建的線程池都實(shí)現(xiàn)了ExecutorService接口,下面為常用的線程池:
創(chuàng)建固定數(shù)目線程的線程池,操作一個(gè)共享的無(wú)邊界隊(duì)列,當(dāng)所有線程都處于活動(dòng)狀態(tài)時(shí),額外的任務(wù)被提交它們將在隊(duì)列中等待,直到線程可用。當(dāng)有線程池掛掉會(huì)重新創(chuàng)建一個(gè)新的
public?static?ExecutorService?newFixedThreadPool(int?nThreads)?{
????????return?new?ThreadPoolExecutor(nThreads,?nThreads,
??????????????????????????????????????0L,?TimeUnit.MILLISECONDS,
??????????????????????????????????????new?LinkedBlockingQueue());
?}
創(chuàng)建一個(gè)可緩存的線程池,可以創(chuàng)建的范圍是0-Integer.MAX_VALUE,當(dāng)有可用線程時(shí)直接使用,當(dāng)沒(méi)有時(shí)創(chuàng)建新的線程并添加到緩存中,提供使用,這種類型的線程池,適合執(zhí)行許多短期的異步任務(wù)的程序,是在執(zhí)行方法之前創(chuàng)建線程,60秒內(nèi)未使用的線程會(huì)被終止并刪除緩存,
public?static?ExecutorService?newCachedThreadPool()?{
????????return?new?ThreadPoolExecutor(0,?Integer.MAX_VALUE,
??????????????????????????????????????60L,?TimeUnit.SECONDS,
??????????????????????????????????????new?SynchronousQueue());
} 創(chuàng)建一個(gè)單線程化的Executor,只會(huì)有一個(gè)線程池,當(dāng)這個(gè)線程池掛掉會(huì)自動(dòng)創(chuàng)建一個(gè)新的
public?static?ExecutorService?newSingleThreadExecutor()?{
???????return?new?FinalizableDelegatedExecutorService
???????????(new?ThreadPoolExecutor(1,?1,
???????????????????????????????????0L,?TimeUnit.MILLISECONDS,
???????????????????????????????????new?LinkedBlockingQueue()));
?} 創(chuàng)建一個(gè)支持定時(shí)及周期性的任務(wù)執(zhí)行的線程池,多數(shù)情況下可用來(lái)替代Timer類
public?static?ScheduledExecutorService?newScheduledThreadPool(int?corePoolSize)?{
????????return?new?ScheduledThreadPoolExecutor(corePoolSize);
?}
?
一般來(lái)說(shuō),CachedTheadPool在程序執(zhí)行過(guò)程中通常會(huì)創(chuàng)建與所需數(shù)量相同的線程,然后在它回收舊線程時(shí)停止創(chuàng)建新線程,因此它是合理的Executor的首選,只有當(dāng)這種方式會(huì)引發(fā)問(wèn)題時(shí)(比如需要大量長(zhǎng)時(shí)間面向連接的線程時(shí)),才需要考慮用FixedThreadPool
?
下面提供一個(gè)固定大小的線程池的使用案例:
public?static?void?main(String[]?args)?{
????try?{
????????ExecutorService?threadPool?=?Executors.newFixedThreadPool(10);
????????for?(int?i?=?0;?i?<15;?i++)?{
??????????//主要通過(guò)submit方法執(zhí)行調(diào)用,可以接收Runnable,Callable
????????????Future執(zhí)行結(jié)果如下:

?
?
粉絲福利:108本java從入門到大神精選電子書領(lǐng)取
???
?長(zhǎng)按上方鋒哥微信二維碼?2 秒備注「1234」即可獲取資料以及可以進(jìn)入java1234官方微信群
感謝點(diǎn)贊支持下哈?![]()
