在進行講解執行緒的創建方式之前,首先了解下什么是行程,什么是執行緒,行程與執行緒之間的關系等
什么是行程?
其實當一個程式進入記憶體運行時,就是一個行程,行程是處于運行中的程式,并且具有一定的獨立功能,行程是系統進行資源分配和調度的一個獨立單位,具有獨立性,動態性,并發性,這里的獨立性指的是在系統中獨立存在,有獨立資源,有獨立地址空間,沒有行程允許,不會跟別的行程互動;動態性指的是行程在系統中有生命周期以及各種不同的狀態,這也是跟程式的區別,行程加入了時間的概念;并發性指的是行程間可以在單處理器上并發執行,獨立互不影響
那什么是執行緒呢?
多執行緒其實就是擴展了多行程的概念,使一個行程可以同時并發處理多個任務,可以看成是輕量級的行程;執行緒是行程的組成部分,一個行程可以有多個執行緒,執行緒可以有自己的堆疊,程式計數器,區域變數,但是沒有系統資源,執行緒是必須有一個父行程的,他與父行程的其他執行緒是共享全部資源,執行緒的調度與管理是由父行程負責為完成
簡單來說就是,作業系統可以同時執行多個任務,每個任務就是行程,行程可以同時執行多個任務,每個任務就是執行緒
如何創建多執行緒?
創建多執行緒的方式可以概括為四種:
1,繼承Thread類,重寫run()方法
2,實作Runnable介面,重寫run()方法
3,實作Callable介面, 重寫call()方法,借助Future執行
4,借助Executor框架使用執行緒池創建執行緒
具體執行緒創建方式如下:
一:繼承Thread類創建執行緒
class MyThead extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ": 繼承Thread執行緒啦");
}
}
呼叫線層的start()方法啟動執行緒
new MyThead().start();
執行結果如下:
![]()
注:Thread其實也是實作了Runnable介面
二:實作Runnable介面創建執行緒
class MyRunnable implements Runnable {
public void run() {
System.out.println(Thread.currentThread().getName() + ": 實作Runnable執行緒啦");
}
}
借助Thread類呼叫線層的start()方法啟動執行緒
new Thread(new MyRunnable()) .start();
執行結果如下:
![]()
三:使用Callable和Future介面創建執行緒
Java5開始提供Callable介面,提供call方法作為執行緒的執行體,可以看成是Runnable介面的增強版本,增強點在于call()方法可以有回傳值,并且可以拋出例外,由于Callable是新增的介面,不能作為Thread的target使用,所以Java5里提供了Future介面,該介面實作了Runnable,Future的實作類FutureTask類用來包裝Callable物件,那么該怎么呼叫并獲取回傳值呢?下面用代碼進行展示用法:
創建Callable物件
class MyCallable implements Callable<Map<String, String>> {
public Map<String, String> call() throws Exception {
HashMap<String, String> map = new HashMap<String, String>();
map.put("returnCode", "000000");
map.put("messgae", Thread.currentThread().getName() + ":Callable創建執行緒成功");
return map;
}
}
啟動執行緒
public static void main(String[] args) {
FutureTask<Map<String, String>> future = new FutureTask(new MyCallable());
new Thread(future).start();
try {
/**
* get()回傳Callable任務里的call()回傳值
* get方法是一個阻塞方法,對于task內置了一些任務狀態,當任務狀態為新建0或者初始化完成的時候1的時候會阻塞
* 需要根據設定的時間阻塞,沒有設定時會一直進行阻塞,一直到有結果回傳
*/
Map<String, String> resultMap = future.get();
System.out.println(resultMap);
} catch (Exception e) {
e.printStackTrace();
}
}
執行結果如下:
![]()
四:借助Executor框架使用執行緒池創建執行緒
- Executors提供了一系列工廠方法用于創先執行緒池,創建的執行緒池都實作了ExecutorService介面,下面為常用的執行緒池:
創建固定數目執行緒的執行緒池,操作一個共享的無邊界佇列,當所有執行緒都處于活動狀態時,額外的任務被提交它們將在佇列中等待,直到執行緒可用,當有執行緒池掛掉會重新創建一個新的
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
- 創建一個可快取的執行緒池,可以創建的范圍是0-Integer.MAX_VALUE,當有可用執行緒時直接使用,當沒有時創建新的執行緒并添加到快取中,提供使用,這種型別的執行緒池,適合執行許多短期的異步任務的程式,是在執行方法之前創建執行緒,60秒內未使用的執行緒會被終止并洗掉快取,
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
- 創建一個單執行緒化的Executor,只會有一個執行緒池,當這個執行緒池掛掉會自動創建一個新的
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
- 創建一個支持定時及周期性的任務執行的執行緒池,多數情況下可用來替代Timer類
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
一般來說,CachedTheadPool在程式執行程序中通常會創建與所需數量相同的執行緒,然后在它回收舊執行緒時停止創建新執行緒,因此它是合理的Executor的首選,只有當這種方式會引發問題時(比如需要大量長時間面向連接的執行緒時),才需要考慮用FixedThreadPool
下面提供一個固定大小的執行緒池的使用案例:
public static void main(String[] args) {
try {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
for (int i = 0; i <15; i++) {
//主要通過submit方法執行呼叫,可以接收Runnable,Callable
Future<Map<String, String>> future = threadPool.submit(new MyCallable());
Map<String, String> resultMap = future.get();
System.out.println(resultMap);
}
threadPool.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
執行結果如下:
下一篇再介紹相關執行緒的其他知識,歡迎討論,一起學習
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/122709.html
標籤:其他
上一篇:Python 的安裝
