【Java基礎】:執行緒的建立和啟動
單執行緒的程式在實際情況中,往往功能是十分有限的,因此隨著業務邏輯的複雜度增加好程式併發量的增大,就引入了多執行緒的概念。Java語言提供了非常優秀的多執行緒技術支援,程式可以通過非常簡單的方式來建立新的執行緒並啟動之。
Java使用Thread類代表執行緒,所有的執行緒物件都必須是Thread類或其子類的例項。通常有三種方式來建立新的執行緒。
大家都比較熟悉的是前兩種方式,一種是通過繼承Thread類來建立,另一種是通過實現Runnable介面來建立。因為這兩種方式大家都比較熟悉,我也就不在這裡去詳細說明如何實現了,直接看第三種方式是什麼。
第三種方式:使用Callable和Future建立執行緒
從Java 5開始,Java提供了Callable介面,熟悉的人可能會感覺和Runnable介面有點像,可以認為是Callable介面的增強版,Callable介面提供了一個call()方法作為執行緒執行體,但是要注意的是call()方法比run()方法功能更加強大。具體體現在兩點:
1call方法可以有返回值
2call方法可以宣告丟擲異常
因此完全可以提供一個Callable物件作為Thread的target,而該執行緒的執行緒執行體就是該Callable物件的call方法。問題是:Callable介面使Java 5新增的介面,而且它不是Runnable介面的子介面,所以Callable物件不能直接作為Thread的target。而且call方法還有一個返回值——call方法並不是直接呼叫,它是作為執行緒執行體被呼叫的。那麼如何獲取call方法的返回值呢?
Java5提供了Future介面來代表Callable介面裡的call方法的返回值,併為Future介面提供了一個FutureTask實現類,該實現類實現了Future介面,並且實現了Runnable介面——可以作為Thread類的target。
在Future介面裡定義瞭如下幾個公共方法來控制它關聯的Callable任務。
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;
}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;
}
cancel(booleanmayInterruptIfRunning):試圖取消該Future裡關聯的Callable任務。
Vget():返回Callable任務裡call方法的返回值,呼叫該方法將導致程式阻塞,必須等到子執行緒結束後才會得到返回值。
Vget(long timeOut, TimeUnit unit):返回Callable任務裡call方法的返回值,該方法讓程式最多阻塞timeout和unit指定的時間,如果經過指定時間後Callable任務依然沒有返回值,將會丟擲TimeoutException異常。
BooleanisCancelled():如果在Callable任務正常完成前被取消,則返回true。
BooleanisDone():如果Callable任務已經完成,則返回true。
需要注意的是,Callable介面有泛型限制,Callable介面裡的泛型形參型別與call方法返回值型別相同。而且Callable介面使函式式介面,因此可以使用Lambda表示式建立Callable物件。
下面我們就通過程式碼來看如何使用Callable和Future來建立並且啟動執行緒:
public class ThirdThread
{
public static void main(String[] args)
{
// 建立Callable物件
ThirdThread rt = new ThirdThread();
// 先使用Lambda表示式建立Callable<Integer>物件
// 使用FutureTask來包裝Callable物件
FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)() -> {
int i = 0;
for ( ; i < 100 ; i++ )
{
System.out.println(Thread.currentThread().getName()
+ " 的迴圈變數i的值:" + i);
}
// call()方法可以有返回值
return i;
});
for (int i = 0 ; i < 100 ; i++)
{
System.out.println(Thread.currentThread().getName()
+ " 的迴圈變數i的值:" + i);
if (i == 20)
{
// 實質還是以Callable物件來建立、並啟動執行緒
new Thread(task , "有返回值的執行緒").start();
}
}
try
{
// 獲取執行緒返回值
System.out.println("子執行緒的返回值:" + task.get());
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
上面程式中使用了Lambda表示式直接建立了Callable物件,這樣就無須先建立Callable實現類,再建立Callable物件了。實現Callable介面與實現Runnable介面並沒有太大的區別,只是Callable的call方法允許宣告丟擲異常,而且允許帶返回值。
相關文章
- Concurrency(二:建立和啟動執行緒)執行緒
- Java基礎:執行緒的三種建立方式Java執行緒
- Java 執行緒基礎Java執行緒
- java 執行緒淺解01[建立以及啟動]Java執行緒
- Java執行緒池一:執行緒基礎Java執行緒
- JAVA多執行緒和併發基礎Java執行緒
- Java 多執行緒基礎(四)執行緒安全Java執行緒
- java - 多執行緒基礎Java執行緒
- Java 多執行緒基礎(十一)執行緒優先順序和守護執行緒Java執行緒
- Java 多執行緒基礎(八)執行緒讓步Java執行緒
- Java多執行緒-基礎篇Java執行緒
- Java 基礎(十四)執行緒——下Java執行緒
- Java 多執行緒基礎 - CyclicBarrierJava執行緒
- Java基礎之執行緒安全Java執行緒
- [Java基礎]虛擬執行緒Java執行緒
- JAVA中執行緒的建立Java執行緒
- Java執行緒篇——執行緒的開啟Java執行緒
- Java基礎之執行緒那些事Java執行緒
- Java-基礎-執行緒入門Java執行緒
- java基礎 關於執行緒安全Java執行緒
- JAVA_基礎多執行緒(一)Java執行緒
- Java併發基礎01:揭祕傳統執行緒技術中建立執行緒的兩種方式Java執行緒
- Java 多執行緒基礎(六)執行緒等待與喚醒Java執行緒
- 執行緒和程式基礎以及多執行緒的基本使用(iOS)執行緒iOS
- 【JUC】1-Java執行緒的啟動Java執行緒
- 執行緒基礎執行緒
- 【Java】執行緒的建立方式Java執行緒
- 玩轉java多執行緒 之多執行緒基礎 執行緒狀態 及執行緒停止實戰Java執行緒
- java基礎(五):談談java中的多執行緒Java執行緒
- 程序和執行緒基礎內容執行緒
- Java基礎之多執行緒程式設計Java執行緒程式設計
- 【JAVA】【面試】【基礎篇】- 執行緒、鎖Java面試執行緒
- Java併發基礎(2)------執行緒池Java執行緒
- java基礎之執行緒 認識volatileJava執行緒
- java基礎-多執行緒初步瞭解Java執行緒
- 程式執行緒篇——程式執行緒基礎執行緒
- 面試官:Java 執行緒如何啟動的?面試Java執行緒
- c#基礎,單執行緒,跨執行緒訪問和執行緒帶引數C#執行緒
- 最全java多執行緒學習總結1--執行緒基礎Java執行緒