如題 (總結要點)
- 使用ThreadPoolExecutor來建立線程,使用Callable + Future 來執行並探知線程執行狀況;
- V get (long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException 同上面的get功能同樣,多了設置超時時間。參數timeout指定超時時間,uint指定時間的單位,在枚舉類TimeUnit中有相關的定義。若是計算超時,將拋出TimeoutException。
- 能夠轉換爲FutureTask: FutureTask
task = (FutureTask
) poolExecutor.submit(new MyRunner(500));
- 畢竟:class FutureTask
implements RunnableFuture
,interface RunnableFuture
extends Runnable, Future
;
- FutureTask能夠做爲線程扔到線程池中運行,而且還能夠像下面的Future同樣探知線程的執行狀況。
- 下面的線程池poolExecutor.submit 返回的是interface RunnableFuture
extends Runnable, Future
(查看源碼可知):
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
借鑑學習文章列表
- 連接1:https://www.cnblogs.com/dolphin0520/p/3949310.html
- 連接2:《java併發編程的藝術》
- https://blog.csdn.net/yangliuhbhd/article/details/70276153
1.主題
Future接口提供方法來檢測任務是否被執行完,等待任務執行完得到結果,也能夠設置任務執行的超時時間。這個設置超時的方法就是實現Java程序執行超時的關鍵。
Future接口是一個泛型接口,嚴格的格式應該是Future<V>,其中V表明了Future執行的任務返回值的類型。 Future接口的方法介紹以下:
boolean cancel (boolean mayInterruptIfRunning) 取消任務的執行。參數指定是否當即中斷任務執行,或者等等任務結束
boolean isCancelled () 任務是否已經取消,任務正常完成前將其取消,則返回 true
boolean isDone () 任務是否已經完成。須要注意的是若是任務正常終止、異常或取消,都將返回true
V get () throws InterruptedException, ExecutionException 等待任務執行結束,而後得到V類型的結果。InterruptedException 線程被中斷異常, ExecutionException任務執行異常,若是任務被取消,還會拋出CancellationException
V get (long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException 同上面的get功能同樣,多了設置超時時間。參數timeout指定超時時間,uint指定時間的單位,在枚舉類TimeUnit中有相關的定義。若是計算超時,將拋出TimeoutException
Future的實現類有java.util.concurrent.FutureTask<V>即 javax.swing.SwingWorker<T,V>。一般使用FutureTask來處理咱們的任務。FutureTask類同時又實現了Runnable接口,因此能夠直接提交給Executor執行。
2. 代碼
/**
* 測試子線程,計算100之內的整數和
*/
class MyRunner implements Callable<Integer>{
private int sleepTime ;
public MyRunner(int sleepTime) {
this.sleepTime = sleepTime;
}
Logger logger = Logger.getLogger("myRunner");
@Override
public Integer call() throws Exception {
logger.info("子線程開始運行");
Thread.sleep(sleepTime);
int sum = 0;
for(int i=1;i<=100;i++){
sum += i;
}
logger.info(sleepTime/1000.0+"s後,子線程結束運行.100之內的正數和爲:"+sum);
return sum;
}
}
3.測試 主線程啓動
import java.util.concurrent.*;
import java.util.logging.Logger;
/** https://www.cnblogs.com/dolphin0520/p/3949310.html
* 《java併發編程的藝術》
*/
public class Test {
private static Logger logger = Logger.getLogger("Test");
public static void main(String[] args) {
/**
* 測試Callable 接口
* 這是一個泛型接口,call()函數返回的類型就是傳遞進來的V類型
* Callable通常是和ThreadPoolExecutor配合來使用的
* 使用futureTask
*/
BlockingQueue<Runnable> queue = new SynchronousQueue<>();
ThreadFactory nameThreadFactory = new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
};
ThreadPoolExecutor poolExecutor =
new ThreadPoolExecutor(2, 2, 0, TimeUnit.MILLISECONDS, queue, nameThreadFactory);
/**
* 將實現Callable 或者runnable 接口的類提交給線程池便可
* */
Future<Integer> task = poolExecutor.submit(new MyRunner(500));
poolExecutor.shutdown();
try {
task.get(100,TimeUnit.MILLISECONDS);
logger.info("打印submit執行結果?是否done?");
boolean done = task.isDone();
logger.info(String.valueOf(done));
// 若是沒有完成,取消當前線程的運行
if(!done){
task.cancel(true);
}
} catch (InterruptedException e) {
task.cancel(true);
} catch (ExecutionException e) {
task.cancel(true);
} catch (TimeoutException e) {
logger.info("超時");
task.cancel(true);
}
logger.info("全部任務執行完畢");
}
}
測試結果
八月 16, 2019 10:05:18 上午 com.thread.MyRunner call
信息: 子線程開始運行
八月 16, 2019 10:05:18 上午 com.thread.Test main
信息: 超時
八月 16, 2019 10:05:18 上午 com.thread.Test main
信息: 全部任務執行完畢
測試結果2 修改 探知時間 task.get(1000,TimeUnit.MILLISECONDS);
八月 16, 2019 10:25:20 上午 com.thread.MyRunner call
信息: 子線程開始運行
八月 16, 2019 10:25:20 上午 com.thread.MyRunner call
信息: 0.5s後,子線程結束運行.100之內的正數和爲:5050
八月 16, 2019 10:25:20 上午 com.thread.Test main
信息: 打印submit執行結果?是否done?
八月 16, 2019 10:25:20 上午 com.thread.Test main
信息: true
八月 16, 2019 10:25:20 上午 com.thread.Test main
信息: 全部任務執行完畢