Java多線程Thread , Future , Callable , FutureTask的使用
Thread創(chuàng)建一個線程
在想要使用多線程的技術(shù)來進(jìn)行相應(yīng)的操作的時候: 可以含有以下的方向來進(jìn)行設(shè)計(jì)思考! 在創(chuàng)建一個線程的時候通常是創(chuàng)建一個Thread的。 但是這個Thread,是含有多種方式來進(jìn)行創(chuàng)建操作的。 例如: 直接使用空參數(shù)的構(gòu)造器進(jìn)行創(chuàng)建操作:
System.out.println("start:" + System.currentTimeMillis()); Thread thread = new Thread(); thread.start(); System.out.println("end:" + System.currentTimeMillis());
這樣執(zhí)行是沒有什么效果的。這種情況就是你啟動了一個線程,但是這個線程是沒有任何事情要干的。
時間是過的飛起的。
但是還有一種方法也是可以進(jìn)行線程的啟動操作的。
使用含有參數(shù)方法的構(gòu)造器進(jìn)行創(chuàng)建線程:
System.out.println(Thread.currentThread() + "----start:" + System.currentTimeMillis()); Thread thread = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("我正在執(zhí)行一個任務(wù),不要打擾我!"); System.out.println(Thread.currentThread()); } }); thread.start(); System.out.println(Thread.currentThread() + "----end:" + System.currentTimeMillis());
這種是開啟一個線程讓其來進(jìn)行線程任務(wù)的執(zhí)行操作的。
但是你有沒有發(fā)現(xiàn),這種方式有一點(diǎn)缺點(diǎn)的。
這個開啟的線程是相當(dāng)于我要讓其進(jìn)行一些子任務(wù)的執(zhí)行操作的。
Thread進(jìn)行異步處理
類似于我是老師,我想讓學(xué)習(xí)委員去辦公室?guī)臀夷靡恍鴣淼摹4藭r學(xué)習(xí)委員已經(jīng)出發(fā)了,但是我想起來我好像是帶了書的。我想要讓學(xué)習(xí)委員不要去辦公室拿書了。
若我直接采用這種方式來來進(jìn)行執(zhí)行操作的話,是無法滿足我的需求的。只要是我叫他去拿書了,她就會喊不回來的。
那是否能對這種方式進(jìn)行相應(yīng)的改造操作呢???
java的開發(fā)者是給了我們一種實(shí)現(xiàn)的方式的。
使用Future的接口滿足需求。
相應(yīng)的解釋:
A Future 表示異步計(jì)算的結(jié)果。提供了用于檢查計(jì)算是否完成、等待計(jì)算完成以及檢索計(jì)算結(jié)果的方法。只有在計(jì)算完成后才能使用方法 get 檢索結(jié)果,必要時會阻止,直到它準(zhǔn)備就緒。取消是通過該 cancel 方法執(zhí)行的。提供了其他方法來確定任務(wù)是正常完成還是已取消。計(jì)算完成后,無法取消計(jì)算。如果為了可取消性而使用 a Future ,但不提供可用的結(jié)果,則可以聲明表單 Future<?> 的類型,并作為基礎(chǔ)任務(wù)的結(jié)果返回 null 。
public interface Future<V> { ? /** * Attempts to cancel execution of this task. This attempt will * fail if the task has already completed, has already been cancelled, * or could not be cancelled for some other reason. If successful, * and this task has not started when {@code cancel} is called, * this task should never run. If the task has already started, * then the {@code mayInterruptIfRunning} parameter determines * whether the thread executing this task should be interrupted in * an attempt to stop the task. * * <p>After this method returns, subsequent calls to {@link #isDone} will * always return {@code true}. Subsequent calls to {@link #isCancelled} * will always return {@code true} if this method returned {@code true}. * * @param mayInterruptIfRunning {@code true} if the thread executing this * task should be interrupted; otherwise, in-progress tasks are allowed * to complete * @return {@code false} if the task could not be cancelled, * typically because it has already completed normally; * {@code true} otherwise */ boolean cancel(boolean mayInterruptIfRunning); ? /** * Returns {@code true} if this task was cancelled before it completed * normally. * * @return {@code true} if this task was cancelled before it completed */ boolean isCancelled(); ? /** * Returns {@code true} if this task completed. * * Completion may be due to normal termination, an exception, or * cancellation -- in all of these cases, this method will return * {@code true}. * * @return {@code true} if this task completed */ boolean isDone(); ? /** * Waits if necessary for the computation to complete, and then * retrieves its result. * * @return the computed result * @throws CancellationException if the computation was cancelled * @throws ExecutionException if the computation threw an * exception * @throws InterruptedException if the current thread was interrupted * while waiting */ V get() throws InterruptedException, ExecutionException; ? /** * Waits if necessary for at most the given time for the computation * to complete, and then retrieves its result, if available. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return the computed result * @throws CancellationException if the computation was cancelled * @throws ExecutionException if the computation threw an * exception * @throws InterruptedException if the current thread was interrupted * while waiting * @throws TimeoutException if the wait timed out */ V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
通過這個接口就可以實(shí)現(xiàn)相對應(yīng)的功能操作了。
給予了一個接口想要將其進(jìn)行實(shí)現(xiàn)操作就得要相關(guān)的實(shí)現(xiàn)類。
登場的就是FutureTask的類進(jìn)行操作的。
public FutureTask(Runnable runnable, V result) { this.callable = Executors.callable(runnable, result); this.state = NEW; // ensure visibility of callable }
執(zhí)行一下相關(guān)的代碼:
FutureTask<String> stringFutureTask = new FutureTask<String>(new Runnable() { @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("我正在執(zhí)行一個任務(wù),不要打擾我!"); System.out.println(Thread.currentThread()); } } , null); ? Thread futureThread = new Thread(stringFutureTask); futureThread.start(); // 是可以滿足對一個進(jìn)行任務(wù)的取消工作的 // stringFutureTask.cancel(true); System.out.println(stringFutureTask.isCancelled()); ? ? Thread futureThread1 = new Thread(stringFutureTask); futureThread1.start();
第二個 futureThread1 是不會執(zhí)行的。
解釋原因:
在Java中,FutureTask
只能執(zhí)行一次。當(dāng)您嘗試第二次執(zhí)行相同的FutureTask
實(shí)例時,它不會執(zhí)行任何操作。這是因?yàn)?code>FutureTask的狀態(tài)在第一次執(zhí)行后會改變,它不會重新開始。如果第一個線程(futureThread
)已經(jīng)開始執(zhí)行stringFutureTask
,那么第二個線程(futureThread1
)嘗試開始相同的stringFutureTask
時,將不會有任何效果,因?yàn)?code>FutureTask的狀態(tài)已經(jīng)不是初始狀態(tài)了。
這里是一些關(guān)鍵點(diǎn):
FutureTask
在執(zhí)行后會進(jìn)入完成狀態(tài)。如果嘗試再次執(zhí)行一個已經(jīng)完成的
FutureTask
,它不會重新執(zhí)行。如果需要重新執(zhí)行任務(wù),您需要創(chuàng)建一個新的
FutureTask
實(shí)例。
上面相關(guān)的例子,已經(jīng)將一個老師叫學(xué)習(xí)委員去辦公室拿書的例子叫停了。也就是說現(xiàn)在是實(shí)現(xiàn)了異步處理的操作。
帶有參數(shù)的返回線程處理
我現(xiàn)在還有一個需求,是干嘛的呢???我不是喊學(xué)習(xí)委員去辦公室拿書了嗎??我想要那個他拿到的書給我手上。這個功能是怎么實(shí)現(xiàn)的呢?
也就是含有返回值的相關(guān)的例子!!!
JUC給了一個方法,是可以直接將一個Callable的接口傳過來的
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable }
使用這個接口作為參數(shù)傳給的FutureTask進(jìn)行任務(wù)的初始化操作。
我們知道Callable接口是有返回值的。那么就可以類似于得到相應(yīng)的那一本書了!??!
操作實(shí)現(xiàn):
FutureTask<String> stringFutureTask = new FutureTask<String>(new Callable<String>() { @Override public String call() throws Exception { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("我正在執(zhí)行一個任務(wù),不要打擾我!"); return "老師,我拿到書了"; } }); ? Thread thread = new Thread(stringFutureTask); thread.start(); System.out.println(stringFutureTask.get());
將得到的東西進(jìn)行返回操作。這樣的話就可以實(shí)現(xiàn)三種基本的功能操作了。
到此這篇關(guān)于Java多線程Thread , Future , Callable , FutureTask的使用的文章就介紹到這了,更多相關(guān)Java Thread , Future , Callable , FutureTask內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java中關(guān)于ThreadLocal的隱式引用詳解
- Java中的Random和ThreadLocalRandom詳細(xì)解析
- Java中的ThreadLocal源碼及弱引用解析
- Java中ThreadLocal共享變量的使用
- Java中的ScheduledThreadPoolExecutor定時任務(wù)詳解
- Java中的FutureTask實(shí)現(xiàn)代碼實(shí)例
- Java中的FutureTask源碼解析
- 一文搞懂Runnable、Callable、Future、FutureTask及應(yīng)用
- Java并發(fā)編程中的Callable、Future和FutureTask詳解
- Java中Future和FutureTask的示例詳解及使用
- Java多線程 Callable、Future 和FutureTask
相關(guān)文章
JDK安裝與配置超級詳細(xì)教程(包含二個或多個JDK的同時安裝)
這篇文章主要給大家介紹了關(guān)于JDK安裝與配置(包含二個或多個JDK的同時安裝)的相關(guān)資料,對于Java學(xué)習(xí)者來說,一臺電腦拿到手肯定要配置JDK,但是對于新手來說還是容易出錯,需要的朋友可以參考下2023-10-10Java?Http請求方式之RestTemplate常用方法詳解
這篇文章主要為大家介紹了Java?Http請求方式之RestTemplate常用方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09

Java 中責(zé)任鏈模式實(shí)現(xiàn)的三種方式

Spring中的注解@Autowired實(shí)現(xiàn)過程全解(@Autowired 背后的故事)

Mybatis-plus如何查詢返回對象內(nèi)有List<String>屬性