[TOC]
## 1. 繼承Thread類
通過繼承Thread類來創建并啟動多線程的步驟如下:
**1. 定義一個類繼承Thread類,并重寫Thread類的run()方法,run()方法的方法體就是線程要完成的任務,因此把run()稱為線程的執行體;**
**2. 創建該類的實例對象,即創建了線程對象;**
**3. 調用線程對象的start()方法來啟動線程;**
~~~
package com.tuna.javatest.thread;
public class ExtendThread extends Thread {
private int i;
public void run() {
for (; i < 10; i++) {
//當通過繼承Thread類的方式實現多線程時,可以直接使用this獲取當前執行的線程
System.out.println(this.getName() + " " + i);
}
}
public static void main(String[] args) {
for (int j = 0; j < 5; j++) {
//調用Thread類的currentThread()方法獲取當前線程
System.out.println(Thread.currentThread().getName() + " " + j);
//創建并啟動第一個線程
new ExtendThread().start();
}
}
}
~~~
## 2. 實現Runnable接口
這種方式創建并啟動多線程的步驟如下:
**1. 定義一個類實現Runnable接口;**
**2. 創建該類的實例對象obj;**
**3. 將obj作為構造器參數傳入Thread類實例對象,這個對象才是真正的線程對象;**
**4. 調用線程對象的start()方法啟動該線程;**
推薦這種寫法,體現設計與實現分離的思想
~~~
package com.tuna.javatest.thread;
public class ImpRunnable implements Runnable {
private int i;
@Override
public void run() {
for(;i < 5;i++) {
//當線程類實現Runnable接口時,要獲取當前線程對象只有通過Thread.currentThread()獲取
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
public static void main(String[] args) {
for(int j = 0;j < 30;j++) {
System.out.println(Thread.currentThread().getName() + " " + j);
ImpRunnable thread_target = new ImpRunnable();
new Thread(thread_target,j+"").start();
}
}
}
~~~
## 3. Callable和Future接口創建線程
### 3.1 Callable接口
通過實現Runnable接口創建多線程時,Thread類的作用就是把run()方法包裝成線程的執行體,那么,是否可以直接把任意方法都包裝成線程的執行體呢?從JAVA5開始,JAVA提供提供了Callable接口,該接口是Runnable接口的增強版,Callable接口提供了一個call()方法可以作為線程執行體,但call()方法比run()方法功能更強大,call()方法的功能的強大體現在:
1. call()方法可以有返回值;
2. call()方法可以聲明拋出異常;
從這里可以看出,完全可以提供一個Callable對象作為Thread的target,而該線程的線程執行體就是call()方法。但問題是:Callable接口是JAVA新增的接口,而且它不是Runnable接口的子接口,所以Callable對象不能直接作為Thread的target。還有一個原因就是:call()方法有返回值,call()方法不是直接調用,而是作為線程執行體被調用的,所以這里涉及獲取call()方法返回值的問題。
于是,JAVA5提供了Future接口來代表Callable接口里call()方法的返回值,并為Future接口提供了一個FutureTask實現類,該類實現了Future接口,并實現了Runnable接口,所以FutureTask可以作為Thread類的target,同時也解決了Callable對象不能作為Thread類的target這一問題。
### 3.2 Future接口
是對于具體的Runnable或者Callable任務的執行結果進行**取消**、**查詢是否完成**、**獲取結果** 。必要時可以通過get方法獲取執行結果,該方法會阻塞直到任務返回結果。
接口中有5中方法:
1. **cancel(boolean mayInterruptIfRunning)**
方法用來取消任務,如果取消任務成功則返回true,如果取消任務失敗則返回false。
參數mayInterruptIfRunning表示是否允許取消正在執行卻沒有執行完畢的任務,如果設置true,則表示可以取消正在執行過程中的任務。如果任務已經完成,則無論mayInterruptIfRunning為true還是false,此方法肯定返回false,即如果取消已經完成的任務會返回false;如果任務正在執行,若mayInterruptIfRunning設置為true,則返回true,若mayInterruptIfRunning設置為false,則返回false;如果任務還沒有執行,則無論mayInterruptIfRunning為true還是false,肯定返回true。
2. **isCancelled()**
方法表示任務是否被取消成功,如果在任務正常完成前被取消成功,則返回 true。
3. **isDone()**
方法表示任務是否已經完成,若任務完成,則返回true;
4. **get()**
方法用來獲取執行結果,這個方法會產生阻塞,會一直等到任務執行完畢才返回;
5. **get(long timeout, TimeUnit unit)**
用來獲取執行結果,如果在指定時間內,還沒獲取到結果,就直接返回null。可用在任務超時控制的情形。
### 3.3 線程實現
1. 實現Callable接口并重寫call方法,完成要執行的邏輯
~~~
class Task implements Callable<Object> {
private String args1;
private String args2;
//構造函數,用來向task中傳遞任務的參數
public Task(String args1,String args2) {
this.args1=args1;
this.args2=args2;
}
//任務執行的動作
@Override
public Object call() throws Exception {
for(int i=0;i<10;i++){
System.out.println("call執行任務!");
}
return true;
}
}
~~~
2. 創建FutureTask對象(傳入),將邏輯交給線程
```
public static void main(String[] args) {
Task myTask = new Task("11", "22");//實例化任務,傳遞參數
FutureTask<Object> futureTask = new FutureTask(myTask);//將任務放進FutureTask里
//采用thread來開啟多線程,futuretask繼承了Runnable,可以放在線程池中來啟動執行
Thread thread = new Thread(futureTask);
thread.start();
try {
//get():獲取任務執行結果,如果任務還沒完成則會阻塞等待直到任務執行完成。如果任務被取消則會拋出CancellationException異常,
//如果任務執行過程發生異常則會拋出ExecutionException異常,如果阻塞等待過程中被中斷則會拋出InterruptedException異常。
boolean result = (boolean) futureTask.get();
System.out.println("result:" + result );
} catch (Exception e) {
e.printStackTrace();
}
}
```
3. 完整代碼
~~~
class Task implements Callable<Object> {
private String args1;
private String args2;
//構造函數,用來向task中傳遞任務的參數
public Task(String args1,String args2) {
this.args1=args1;
this.args2=args2;
}
//任務執行的動作
@Override
public Object call() throws Exception {
for(int i=0;i<10;i++){
System.out.println("call執行任務!");
}
return true;
}
public static void main(String[] args) {
Task myTask = new Task("11", "22");//實例化任務,傳遞參數
FutureTask<Object> futureTask = new FutureTask(myTask);//將任務放進FutureTask里
//采用thread來開啟多線程,futuretask繼承了Runnable,可以放在線程池中來啟動執行
Thread thread = new Thread(futureTask);
thread.start();
try {
//get():獲取任務執行結果,如果任務還沒完成則會阻塞等待直到任務執行完成。如果任務被取消則會拋出CancellationException異常,
//如果任務執行過程發生異常則會拋出ExecutionException異常,如果阻塞等待過程中被中斷則會拋出InterruptedException異常。
boolean result = (boolean) futureTask.get();
System.out.println("result:" + result );
} catch (Exception e) {
e.printStackTrace();
}
}
}
~~~
```
call執行任務!
call執行任務!
call執行任務!
call執行任務!
call執行任務!
call執行任務!
call執行任務!
call執行任務!
call執行任務!
call執行任務!
result:true
```
- 計算機網絡
- 基礎_01
- tcp/ip
- http轉https
- Let's Encrypt免費ssl證書(基于haproxy負載)
- what's the http?
- 網關
- 網絡IO
- http
- 工具
- Git
- 初始本地倉庫并上傳
- git保存密碼
- Gitflow
- maven
- 1.生命周期命令
- 聚合與繼承
- 插件管理
- assembly
- 資源管理插件
- 依賴范圍
- 分環境打包
- dependencyManagement
- 版本分類
- 找不到主類
- 無法加載主類
- 私服
- svn
- gradle
- 手動引入第三方jar包
- 打包exe文件
- Windows
- java
- 設計模式
- 七大原則
- 1.開閉原則
- 2. 里式替換原則
- 3. 依賴倒置原則
- 4. 單一職責原則
- 單例模式
- 工廠模式
- 簡單工廠
- 工廠方法模式
- 抽象工廠模式
- 觀察者模式
- 適配器模式
- 建造者模式
- 代理模式
- 適配器模式
- 命令模式
- json
- jackson
- poi
- excel
- easy-poi
- 規則
- 模板
- 合并單元格
- word
- 讀取
- java基礎
- 類路徑與jar
- 訪問控制權限
- 類加載
- 注解
- 異常處理
- String不可變
- 跨域
- transient關鍵字
- 二進制編碼
- 泛型1
- 與或非
- final詳解
- Java -jar
- 正則
- 讀取jar
- map
- map計算
- hashcode計算原理
- 枚舉
- 序列化
- URLClassLoader
- 環境變量和系統變量
- java高級
- java8
- 1.Lambda表達式和函數式接口
- 2.接口的默認方法和靜態方法
- 3.方法引用
- 4.重復注解
- 5.類型推斷
- 6.拓寬注解的應用場景
- java7-自動關閉資源機制
- 泛型
- stream
- 時區的正確理解
- StringJoiner字符串拼接
- 注解
- @RequestParam和@RequestBody的區別
- 多線程
- 概念
- 線程實現方法
- 守護線程
- 線程阻塞
- 筆試題
- 類加載
- FutureTask和Future
- 線程池
- 同步與異步
- 高效簡潔的代碼
- IO
- ThreadLocal
- IO
- NIO
- 圖片操作
- KeyTool生成證書
- 壓縮圖片
- restful
- 分布式session
- app保持session
- ClassLoader.getResources 能搜索到的資源路徑
- java開發規范
- jvm
- 高并發
- netty
- 多線程與多路復用
- 異步與事件驅動
- 五種IO模型
- copy on write
- code style
- 布隆過濾器
- 筆試
- 數據庫
- mybatis
- mybatis與springboot整合配置
- pagehelper
- 分頁數據重復問題
- Java與數據庫之間映射
- 攔截器
- 攔截器應用
- jvm
- 堆內存測試
- 線程棧
- 直接內存
- 內存結構
- 內存模型
- 垃圾回收
- 調優
- 符號引用
- 運行參數
- 方法區
- 分帶回收理論
- 快捷開發
- idea插件
- 注釋模板
- git
- pull沖突
- push沖突
- Excel處理
- 圖片處理
- 合并單元格
- easypoi
- 模板處理
- 響應式編程
- reactor
- reactor基礎
- jingyan
- 規范
- 數據庫