<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          快速了解多線程的一些常見知識點

          共 5162字,需瀏覽 11分鐘

           ·

          2021-10-18 10:05

          在Java編程中,多線程是非常重要知識點. 關(guān)于Java線程有些不可不知的知識點需要牢記,下面就介紹了這些知識點.


          1. 優(yōu)先級

          每個Java線程都有對應(yīng)的優(yōu)先級,高優(yōu)先級的線程比低優(yōu)先級的線有更多的執(zhí)行機(jī)會。新創(chuàng)建的Java線程默認(rèn)的優(yōu)先級是5, 最低是1,最高是10;

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          /**
          * The minimum priority that a thread can have.
          */
          public final static int MIN_PRIORITY = 1;
          /**
          * The default priority that is assigned to a thread.
          */
          public final static int NORM_PRIORITY = 5;
          /**
          * The maximum priority that a thread can have.
          */
          public final static int MAX_PRIORITY = 10;

          Note:如果在一個線程中創(chuàng)建一個新的線程,新線程的默認(rèn)優(yōu)先級和所在線程的優(yōu)先級保持一致。

          2. daemon 或 非daemon

          一個Java線程可以是daemon的也可以是非daemon的,JVM在啟動的時候啟動了main線程,該線程是非daemon;JVM在下面2情況下會退回:

          1. 調(diào)用Runtime.exit()方法

          2. 所有非daemon的線程都結(jié)束了。

          3. 創(chuàng)建線程的方式

          有2種創(chuàng)建線程的方式,一種是繼承Thread類;一種是直接new一個Thread對象,并在構(gòu)造函數(shù)中傳入一個Runnable對象。

          繼承

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          class PrimeThread extends Thread {
          long minPrime;
          PrimeThread(long minPrime) {
          this.minPrime = minPrime;
          }

          public void run() {
          // compute primes larger than minPrime
          }
          }
          PrimeThread p = new PrimeThread(143);
          p.start();

          //new
          class PrimeRun implements Runnable {
          long minPrime;
          PrimeRun(long minPrime) {
          this.minPrime = minPrime;
          }

          public void run() {
          // compute primes larger than minPrime
           . . .
          }
          }
          PrimeRun p = new PrimeRun(143);
          new Thread(p).start();

          4. 線程的狀態(tài)

          JDK中關(guān)于線程狀態(tài)的定義:

          • new : 一個新創(chuàng)建的,沒有調(diào)用start方法的線程處于該狀態(tài);

          • RUNNABLE :可執(zhí)行的,在JVM中是處于執(zhí)行中,但是在等待其它的操作系統(tǒng)資源,如cpu資源;

          • BLOCKED :阻塞的,一個線程在進(jìn)入(或再次進(jìn)入)一個同步方法或同步塊時等待監(jiān)視器鎖時處于該狀態(tài)。

          • WAITING :等待,一個線程在調(diào)用了如下的方法時會處于等待狀態(tài):
            1.Object.wait
            2.Thread.join //正在主線程中調(diào)用一個一個線程的join方法,在主線程處于等待狀態(tài)
            3.LockSupport#park()

          • TIMED_WAITING 等待的,不過該等待狀態(tài)是有時間限制的。一個線程調(diào)用下面的方法會進(jìn)入該狀態(tài):
            1.Thread.sleep
            2.Object.wait
            3.Thread.join
            4.LockSupport.parkNanos
            5.LockSupport.parkUntil

          • TERMINATED 終止,當(dāng)一個線程執(zhí)行完成后處于該狀態(tài)

          5. 線程的調(diào)度

          理想的情況下,每個程序的線程都擁有一個專屬于自己的處理器;在計算機(jī)還不能擁有幾千,甚至幾百萬CPU處理器的情況下,多個線下需要共享僅有的cpu資源,如果分配線程執(zhí)行所需的cpu資源就需要線程調(diào)度器的調(diào)度了。在操作系統(tǒng)層面有自己的線程調(diào)度器,在JVM中也存在Java線程調(diào)度器。

          在Java線程調(diào)度中有2點比較重要:

          1. Java規(guī)范并沒有強制要求每個JVM按照特定的調(diào)度規(guī)則調(diào)用線程,或者必須包含一個線程調(diào)度器。線程調(diào)度的實現(xiàn)完全是依賴平臺的。

          2. 在編寫Java多線程代碼時,我們唯一需要考慮的是不要讓一個線程大量的占用cpu時間(eg.死循環(huán))。

          大多數(shù)平臺上JVM的線程調(diào)度是依賴操作系統(tǒng)本身的線程調(diào)度器的,每個線下有不同的優(yōu)先級,在基于時間片的規(guī)則下,高優(yōu)先級的線程擁有更多的CPU執(zhí)行機(jī)會;相同優(yōu)先級的線程可以按照FIFO調(diào)度。

          6. Runnable、Callable、Future 和 FutureTasek的區(qū)別

          Java中存在Runnable、Callable、Future、FutureTask這幾個與線程相關(guān)的類或者接口,在Java中也是比較重要的幾個概念,我們通過下面的簡單示例來了解一下它們的作用與區(qū)別。

          6.1 Runnable

          Runnable 應(yīng)該是這幾個類我們使用的最多的一個。JDK的文檔說明:如果一個類的實例想要通過一個線程來執(zhí)行,則該類應(yīng)該實現(xiàn)Runnable接口。Runnable被設(shè)計用來對那些處于active狀態(tài)時會執(zhí)行代碼的對象提供一個統(tǒng)一的協(xié)議。例如Thread類就實現(xiàn)了Runnable接口。

          1
          2
          3
          public interface Runnable {
          public abstract void run();
          }

          6.2 Callable

          Callable 表示一個可以攜帶返回結(jié)果的任務(wù)。該接口的實現(xiàn)類需要一個沒有參數(shù)的call方法。Callable 和 Runnable類似,都是被設(shè)計用來被另外一個線程執(zhí)行的任務(wù)。但是Runnable不能返回一個結(jié)果,且不能拋出一個checked異常。

          1
          2
          3
          4
          5
          6
          7
          8
          9
          public interface Callable<V> {
          /**
          * Computes a result, or throws an exception if unable to do so.
          *
          * @return computed result
          * @throws Exception if unable to compute a result
          */
          V call() throws Exception;
          }

          6.3 Future

          一個Futrue表示一個異步計算的結(jié)果。它提供了一系列方法,用來檢測計算是否完成,獲取計算結(jié)果,等待計算結(jié)果等。只能通過get方法獲取計算結(jié)果;如果計算沒有完成,在必要條件下,則get方法一直等待,直到任務(wù)完成。cancel方法用來取消任務(wù)。其它的方法都是用來測試計算是否完成,或是否取消。一旦計算完成后,就不可以被取消。如果你想使用Future,但并不需要返回一個結(jié)果,則可以使用Future并返回null。

          一個簡單的例子(JDK原文):

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          class App {
          ExecutorService executor = ...
          ArchiveSearcher searcher = ...
          void showSearch(final String target) throws InterruptedException {
          Future future = executor.submit(new Callable() {
          public String call() {
          return searcher.search(target);
          }});
          displayOtherThings();
          try{
          displayText(future.get()); // use future
          }catch(ExecutionException ex){
          cleanup(); return;
          }
          }
          }

          6.4 FutureTask

          FutureTask 表示一個可以取消的異步計算任務(wù)。它實現(xiàn)了Runnable接口和Future接口。FutureTask 可以用來包裝Runnable和Callable對象。應(yīng)該FutureTask實現(xiàn)了Runnable接口。同時可以通過被提交到Executor去執(zhí)行。

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          public FutureTask(Callable callable) {  
          if (callable == null)
          throw new NullPointerException();
          this.callable = callable;
          this.state = NEW; // ensure visibility of callable
          }

          public FutureTask(Runnable runnable, V result) {
          this.callable = Executors.callable(runnable, result);
          this.state = NEW; // ensure visibility of callable
          }

          可以看到,Runnable注入會被Executors.callable()函數(shù)轉(zhuǎn)換為Callable類型,即FutureTask最終都是執(zhí)行Callable類型的任務(wù)。該適配函數(shù)的實現(xiàn)如下 :

          1
          2
          3
          4
          5
          public static  Callable callable(Runnable task, T result) {  
          if (task == null)
          throw new NullPointerException();
          return new RunnableAdapter(task, result);
          }

          RunnableAdapter適配器

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          /** 
          * A callable that runs given task and returns given result
          */
          static final class RunnableAdapter<T> implements Callable<T> {
          final Runnable task;
          final T result;
          RunnableAdapter(Runnable task, T result) {
          this.task = task;
          this.result = result;
          }
          public T call() {
          task.run();
          return result;
          }
          }

          7. 總結(jié)

          由于FutureTask實現(xiàn)了Runnable,因此它既可以通過Thread包裝來直接執(zhí)行,也可以提交給ExecuteService來執(zhí)行。
          并且還可以直接通過get()函數(shù)獲取執(zhí)行結(jié)果,該函數(shù)會阻塞,直到結(jié)果返回。因此FutureTask既是Future、
          Runnable,又是包裝了Callable(如果是Runnable最終也會被轉(zhuǎn)換為Callable ), 它是這兩者的合體。

          source: //leokongwq.github.io/2016/10/16/java-runnable-callable-future.html

          喜歡,在看

          瀏覽 41
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩精品人妻 | 影音先锋在线爱爱 | 强伦轩一区二区三区四区 | 插菊花综合网1 | 91久久精品无码一区二区三区 |