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

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