<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      什么是進(jìn)程和線程?

      一條線程指的是進(jìn)程中一個(gè)單一順序的控制流,一個(gè)進(jìn)程中可以并發(fā)多個(gè)線程,每條線程并行執(zhí)行不同的任務(wù)。

      多線程是多任務(wù)的一種特別的形式,但多線程使用了更小的資源開銷。


      一個(gè)進(jìn)程包括由操作系統(tǒng)分配的內(nèi)存空間,包含一個(gè)或多個(gè)線程。一個(gè)線程不能獨(dú)立的存在,它必須是進(jìn)程的一部分。一個(gè)進(jìn)程一直運(yùn)行,直到所有的非守護(hù)線程都結(jié)束運(yùn)行后才能結(jié)束。

      為什么使用多線程?

      使用多線程可以編寫高效率的程序來(lái)達(dá)到充分利用 CPU,可以大大提高系統(tǒng)整體的并發(fā)能力以及性能.

      線程的生命周期

      線程是一個(gè)動(dòng)態(tài)執(zhí)行的過(guò)程,它也有一個(gè)從產(chǎn)生到死亡的過(guò)程。

      下圖顯示了一個(gè)線程完整的生命周期。

      * 新建狀態(tài):
      使用 new 關(guān)鍵字和 Thread 類或其子類建立一個(gè)線程對(duì)象后,該線程對(duì)象就處于新建狀態(tài)。它保持這個(gè)狀態(tài)直到程序 start() 這個(gè)線程.
      * 就緒狀態(tài):
      當(dāng)線程對(duì)象調(diào)用了start()方法之后,該線程就進(jìn)入就緒狀態(tài)。就緒狀態(tài)的線程處于就緒隊(duì)列中,要等待JVM里線程調(diào)度器的調(diào)度。
      * 運(yùn)行狀態(tài):
      如果就緒狀態(tài)的線程獲取 CPU 資源,就可以執(zhí)行 run(),此時(shí)線程便處于運(yùn)行狀態(tài)。處于運(yùn)行狀態(tài)的線程最為復(fù)雜,它可以變?yōu)樽枞麪顟B(tài)、就緒狀態(tài)和死亡狀態(tài)。
      * 阻塞狀態(tài):

      如果一個(gè)線程執(zhí)行了sleep(睡眠)、suspend(掛起)等方法,失去所占用資源之后,該線程就從運(yùn)行狀態(tài)進(jìn)入阻塞狀態(tài)。在睡眠時(shí)間已到或獲得設(shè)備資源后可以重新進(jìn)入就緒狀態(tài)??梢苑譃槿N:
      * 等待阻塞:運(yùn)行狀態(tài)中的線程執(zhí)行 wait() 方法,使線程進(jìn)入到等待阻塞狀態(tài)。
      * 同步阻塞:線程在獲取 synchronized 同步鎖失敗(因?yàn)橥芥i被其他線程占用)。
      * 其他阻塞:通過(guò)調(diào)用線程的 sleep() 或 join() 發(fā)出了 I/O 請(qǐng)求時(shí),線程就會(huì)進(jìn)入到阻塞狀態(tài)。當(dāng)sleep() 狀態(tài)超時(shí),join()
      等待線程終止或超時(shí),或者 I/O 處理完畢,線程重新轉(zhuǎn)入就緒狀態(tài)。
      * 死亡狀態(tài):
      一個(gè)運(yùn)行狀態(tài)的線程完成任務(wù)或者其他終止條件發(fā)生時(shí),該線程就切換到終止?fàn)顟B(tài)。
      創(chuàng)建線程的方式

      java 提供了三種創(chuàng)建線程的方法:實(shí)現(xiàn) Runnable 接口;繼承 Thread 類本身;通過(guò) Callable 和 Future 創(chuàng)建線程。

      1.實(shí)現(xiàn) Runnable 接口

      創(chuàng)建一個(gè)線程,最簡(jiǎn)單的方法是創(chuàng)建一個(gè)實(shí)現(xiàn) Runnable 接口的類,同時(shí)重寫 run()方法.

      然后創(chuàng)建Runnable實(shí)現(xiàn)類的實(shí)例,并以此實(shí)例作為Thread的target對(duì)象,即該Thread對(duì)象才是真正的線程對(duì)象。

      新線程創(chuàng)建之后,你調(diào)用它的 start() 方法它才會(huì)運(yùn)行。
      package com.example.test; /** * @author ydx */ public class RunnableDemo
      implements Runnable{ /** * 線程名稱 */ private String threadName; /** * 構(gòu)造方法 *
      @param threadName 線程名稱 */ public RunnableDemo(String threadName) {
      this.threadName = threadName; } @Override public void run() {
      System.out.println(threadName + " is running"); //業(yè)務(wù) for (int i = 0; i < 5;
      i++) { System.out.println(threadName + " 執(zhí)行 " + i); try { Thread.sleep(100); }
      catch (InterruptedException e) { e.printStackTrace(); } }
      System.out.println(threadName + " is exiting"); } public static void
      main(String[] args) { RunnableDemo runnable1 = new RunnableDemo("thread-1");
      Thread thread1 = new Thread(runnable1); thread1.start(); RunnableDemo runnable2
      = new RunnableDemo("thread-2"); Thread thread2 = new Thread(runnable2);
      thread2.start(); } }
      第一次運(yùn)行結(jié)果如下:
      thread-1 is running thread-1 執(zhí)行 0 thread-2 is running thread-2 執(zhí)行 0 thread-2
      執(zhí)行 1 thread-1 執(zhí)行 1 thread-2 執(zhí)行 2 thread-1 執(zhí)行 2 thread-1 執(zhí)行 3 thread-2 執(zhí)行 3
      thread-1 執(zhí)行 4 thread-2 執(zhí)行 4 thread-2 is exiting thread-1 is exiting
      第二次運(yùn)行結(jié)果如下:
      thread-1 is running thread-1 執(zhí)行 0 thread-2 is running thread-2 執(zhí)行 0 thread-1
      執(zhí)行 1 thread-2 執(zhí)行 1 thread-1 執(zhí)行 2 thread-2 執(zhí)行 2 thread-1 執(zhí)行 3 thread-2 執(zhí)行 3
      thread-2 執(zhí)行 4 thread-1 執(zhí)行 4 thread-1 is exiting thread-2 is exiting
      可以看出兩次運(yùn)行結(jié)果是不一樣的,每次兩個(gè)線程的執(zhí)行順序是隨機(jī)的.

      2.繼承Thread類

      創(chuàng)建一個(gè)線程的第二種方法是創(chuàng)建一個(gè)新的類,該類繼承 Thread 類,然后創(chuàng)建一個(gè)該類的實(shí)例。

      繼承類必須重寫 run() 方法,該方法是新線程的入口點(diǎn)。它也必須調(diào)用 start() 方法才能執(zhí)行。
      package com.example.test; /** * @author ydx */ public class ThreadDemo extends
      Thread { /** * 線程名稱 */ private String threadName; public ThreadDemo(String
      threadName) { this.threadName = threadName; } @Override public synchronized
      void start() { System.out.println(threadName+ " is starting......");
      super.start(); } @Override public void run() { System.out.println(threadName +
      " is running"); //業(yè)務(wù) for (int i = 0; i < 3; i++) {
      System.out.println(threadName + " 執(zhí)行 " + i); try { Thread.sleep(100); } catch
      (InterruptedException e) { e.printStackTrace(); } }
      System.out.println(threadName + " is exiting"); } public static void
      main(String[] args) { ThreadDemo thread1 = new ThreadDemo("thread-1");
      thread1.start(); ThreadDemo thread2 = new ThreadDemo("thread-2");
      thread2.start(); } }
      運(yùn)行結(jié)果如下:
      thread-1 is starting...... thread-2 is starting...... thread-1 is running
      thread-1 執(zhí)行 0 thread-2 is running thread-2 執(zhí)行 0 thread-1 執(zhí)行 1 thread-2 執(zhí)行 1
      thread-2 執(zhí)行 2 thread-1 執(zhí)行 2 thread-2 is exiting thread-1 is exiting
      3.通過(guò) Callable 和 Future 創(chuàng)建線程

      * 創(chuàng)建 Callable 接口的實(shí)現(xiàn)類,并實(shí)現(xiàn) call() 方法,該 call() 方法將作為線程執(zhí)行體,并且有返回值。
      * 創(chuàng)建 Callable 實(shí)現(xiàn)類的實(shí)例,使用 FutureTask 類來(lái)包裝 Callable 對(duì)象,該 FutureTask 對(duì)象封裝了該
      Callable 對(duì)象的 call() 方法的返回值。
      * 使用 FutureTask 對(duì)象作為 Thread 對(duì)象的 target 創(chuàng)建并啟動(dòng)新線程。
      *
      調(diào)用 FutureTask 對(duì)象的 get() 方法來(lái)獲得子線程執(zhí)行結(jié)束后的返回值。
      package com.example.test; import java.util.concurrent.Callable; import
      java.util.concurrent.ExecutionException; import
      java.util.concurrent.FutureTask; /** * @author ydx */ public class CallableTest
      implements Callable<Integer> { @Override public Integer call() throws Exception
      { int sum = 0; for (int i = 0; i < 5; i++) { sum += i; System.out.println(i);
      //sleep 200ms Thread.sleep(200); } return sum; } public static void
      main(String[] args) { long start = System.currentTimeMillis(); CallableTest
      callableTest = new CallableTest(); FutureTask<Integer> futureTask = new
      FutureTask<>(callableTest); new Thread(futureTask, "thread-1").start();
      CallableTest callableTest2 = new CallableTest(); FutureTask<Integer>
      futureTask2 = new FutureTask<>(callableTest2); new Thread(futureTask2,
      "thread-2").start(); try { System.out.println("thread-1的結(jié)果: " +
      futureTask.get()); System.out.println("thread-2的結(jié)果: " + futureTask.get()); }
      catch (InterruptedException e) { e.printStackTrace(); } catch
      (ExecutionException e) { e.printStackTrace(); } long end =
      System.currentTimeMillis(); System.out.println("耗時(shí): " + (end - start) + "ms");
      } }
      運(yùn)行結(jié)果:
      0 0 1 1 2 2 3 3 4 4 thread-1的結(jié)果: 10 thread-2的結(jié)果: 10 耗時(shí): 1004ms
      我們創(chuàng)建了兩個(gè)線程, 每個(gè)線程計(jì)算0~4的和,單個(gè)線程耗時(shí)200ms * 5 =
      1000ms,而最終兩個(gè)線程的總耗時(shí)約1000ms,由此可見(jiàn)兩個(gè)線程是并發(fā)進(jìn)行.

      4.創(chuàng)建線程的三種方式的對(duì)比

      * 使用繼承 Thread 類的方式創(chuàng)建多線程時(shí),編寫簡(jiǎn)單,但是不夠靈活
      * 采用實(shí)現(xiàn) Runnable、Callable 接口的方式創(chuàng)建多線程時(shí),線程類只是實(shí)現(xiàn)了 Runnable 接口或 Callable
      接口,還可以繼承其他類,創(chuàng)建線程比較靈活.
      線程管理

      Java提供了一些方法用于線程狀態(tài)的控制。具體如下:

      1.sleep(線程睡眠)

      如果我們需要讓當(dāng)前正在執(zhí)行的線程暫停一段時(shí)間,并進(jìn)入阻塞狀態(tài),則可以通過(guò)調(diào)用Thread的sleep方法。

      Thread.sleep(long millis)方法,millis參數(shù)設(shè)定睡眠的時(shí)間,以毫秒為單位。當(dāng)睡眠結(jié)束后,就轉(zhuǎn)為就緒(Runnable)狀態(tài)。

      2.wait(線程等待)

      Object類中的wait()方法,導(dǎo)致當(dāng)前的線程等待,直到其他線程調(diào)用此對(duì)象的 notify() 方法或 notifyAll() 喚醒方法.

      3.yield(線程讓步)

      Thread.yield() 方法,暫停當(dāng)前正在執(zhí)行的線程對(duì)象,把執(zhí)行機(jī)會(huì)讓給相同或者更高優(yōu)先級(jí)的線程。

      和sleep()方法不同的是,它不會(huì)進(jìn)入到阻塞狀態(tài),而是進(jìn)入到就緒狀態(tài)。


      yield()方法只是讓當(dāng)前線程暫停一下,重新進(jìn)入就緒的線程池中,讓系統(tǒng)的線程調(diào)度器重新調(diào)度器重新調(diào)度一次,完全可能出現(xiàn)這樣的情況:當(dāng)某個(gè)線程調(diào)用yield()方法之后,線程調(diào)度器又將其調(diào)度出來(lái)重新進(jìn)入到運(yùn)行狀態(tài)執(zhí)行。

      4.join(線程加入)


      join()方法,等待其他線程終止。在當(dāng)前線程中調(diào)用另一個(gè)線程的join()方法,則當(dāng)前線程轉(zhuǎn)入阻塞狀態(tài),直到另一個(gè)進(jìn)程運(yùn)行結(jié)束,當(dāng)前線程再由阻塞轉(zhuǎn)為就緒狀態(tài)。

      5.notify(線程喚醒)


      Object類中的notify()方法,喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程。如果所有線程都在此對(duì)象上等待,則會(huì)選擇喚醒其中一個(gè)線程。選擇是任意性的,并在對(duì)實(shí)現(xiàn)做出決定時(shí)發(fā)生。線程通過(guò)調(diào)用其中一個(gè)
      wait 方法,在對(duì)象的監(jiān)視器上等待。
      直到當(dāng)前的線程放棄此對(duì)象上的鎖定,才能繼續(xù)執(zhí)行被喚醒的線程。被喚醒的線程將以常規(guī)方式與在該對(duì)象上主動(dòng)同步的其他所有線程進(jìn)行競(jìng)爭(zhēng)

      線程的優(yōu)先級(jí)

      每一個(gè) Java 線程都有一個(gè)優(yōu)先級(jí),這樣有助于操作系統(tǒng)確定線程的調(diào)度順序。

      Java 線程的優(yōu)先級(jí)是一個(gè)整數(shù),其取值范圍是 1 (Thread.MINPRIORITY ) - 10 (Thread.MAXPRIORITY )。

      默認(rèn)情況下,每一個(gè)線程都會(huì)分配一個(gè)優(yōu)先級(jí) NORM_PRIORITY(5)。

      具有較高優(yōu)先級(jí)的線程對(duì)程序更重要,并且應(yīng)該在低優(yōu)先級(jí)的線程之前分配處理器資源。但是,線程優(yōu)先級(jí)不能保證線程執(zhí)行的順序,而且非常依賴于平臺(tái)。

      線程池

      線程池,其實(shí)就是一個(gè)容納多個(gè)線程的容器,其中的線程可以反復(fù)使用,省去了頻繁創(chuàng)建線程對(duì)象的操作,無(wú)需反復(fù)創(chuàng)建線程而消耗過(guò)多資源。使用線程池的好處:

      * 降低資源消耗。通過(guò)重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建和銷毀造成的消耗.
      * 提高響應(yīng)速度。當(dāng)任務(wù)到達(dá)時(shí),任務(wù)可以不需要的等到線程創(chuàng)建就能立即執(zhí)行。
      * 提高線程的可管理性。線程是稀缺資源,如果無(wú)限制的創(chuàng)建,不僅會(huì)消耗系統(tǒng)資源,還會(huì)降低系統(tǒng)的穩(wěn)定性,使用線程池可以進(jìn)行統(tǒng)一的分配,調(diào)優(yōu)和監(jiān)控。
      Java通過(guò)Executors提供四種線程池,分別為:

      * newCachedThreadPoo 創(chuàng)建一個(gè)可緩存線程池,如果線程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線程,若無(wú)可回收,則新建線程。
      * newFixedThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待。
      * newScheduledThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池,支持定時(shí)及周期性任務(wù)執(zhí)行。
      * newSingleThreadExecutor 創(chuàng)建一個(gè)單線程化的線程池,它只會(huì)用唯一的工作線程來(lái)執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO,
      LIFO, 優(yōu)先級(jí))執(zhí)行。

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點(diǎn)信息
      問(wèn)題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          嫩模操逼 | ass白嫩少妇ass巨大戾 | 亚洲人成免费 | 黄色网址免费 | 大屁股喷水视频在线观看 | 鲁一鲁色一色鲁寡妇 | beeg中国少妇呻吟 | 无码人妻一区二区三区蜜桃视频 | www.xxxx日本 | 超碰在线网 |