乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Java 線程基礎(chǔ)

       Coder編程 2021-05-01

      本文部分摘自《Java 并發(fā)編程的藝術(shù)》


      線程簡(jiǎn)介

      1. 什么是線程?

      現(xiàn)代操作系統(tǒng)在運(yùn)行一個(gè)程序時(shí),會(huì)為其創(chuàng)建一個(gè)進(jìn)程,一個(gè)進(jìn)程里可以創(chuàng)建多個(gè)線程?,F(xiàn)代操作系統(tǒng)調(diào)度的最小單元是線程,也叫輕量級(jí)進(jìn)程。這些線程都擁有各自的計(jì)數(shù)器、堆棧和局部變量等屬性,并且能訪問(wèn)共享的內(nèi)存變量。處理器在這些線程上高速切換,讓使用者覺(jué)得這些線程在同時(shí)執(zhí)行

      2. 為什么使用多線程?

      使用多線程的原因主要有以下幾點(diǎn):

      • 更多的處理器核心

        通過(guò)使用多線程技術(shù),將計(jì)算邏輯分配到多個(gè)處理器核心上,可以顯著減少程序的處理時(shí)間

      • 更快的響應(yīng)時(shí)間

        有時(shí)我們會(huì)編寫一些較為復(fù)雜的代碼(主要指業(yè)務(wù)邏輯),可以使用多線程技術(shù),將數(shù)據(jù)一致性不強(qiáng)的操作派發(fā)給其他線程處理(也可以使用消息隊(duì)列)。這樣做的好處是響應(yīng)用戶請(qǐng)求的線程能夠盡可能快地處理完成,縮短了響應(yīng)時(shí)間

      • 更好的編程模型

        Java 已經(jīng)為多線程編程提供了一套良好的編程模型,開(kāi)發(fā)人員只需根據(jù)問(wèn)題需要建立合適的模型即可


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

      現(xiàn)代操作系統(tǒng)基本采用時(shí)分的形式調(diào)度運(yùn)行的線程,操作系統(tǒng)會(huì)分出一個(gè)個(gè)時(shí)間片,線程分配到若干時(shí)間片,當(dāng)線程的時(shí)間片用完了發(fā)生線程調(diào)度,并等待下次分配。線程分配到的時(shí)間片多少也就決定了線程使用處理器資源的多少,而線程優(yōu)先級(jí)就是決定線程需要多或少分配一些處理器資源的線程屬性

      在 Java 線程中,通過(guò)一個(gè)整型成員變量 priority 來(lái)控制優(yōu)先級(jí),優(yōu)先級(jí)的范圍從 1 ~ 10,在線程構(gòu)建時(shí)可以通過(guò) setPriority(int) 方法來(lái)修改優(yōu)先級(jí),默認(rèn)優(yōu)先級(jí)是 5,優(yōu)先級(jí)高的線程分配時(shí)間片的數(shù)量要多于優(yōu)先級(jí)低的線程。不過(guò),在不同的 JVM 以及操作系統(tǒng)上,線程規(guī)劃會(huì)存在差異,有些操作系統(tǒng)甚至?xí)雎跃€程優(yōu)先級(jí)的設(shè)定

      public class Priority {
      
          private static volatile boolean notStart = true;
          private static volatile boolean notEnd = true;
      
          public static void main(String[] args) throws Exception {
              List<Job> jobs = new ArrayList<Job>();
              for (int i = 0; i < 10; i++) {
                  int priority = i < 5 ? Thread.MIN_PRIORITY : Thread.MAX_PRIORITY;
                  Job job = new Job(priority);
                  jobs.add(job);
                  Thread thread = new Thread(job, "Thread:" + i);
                  thread.setPriority(priority);
                  thread.start();
              }
              notStart = false;
              TimeUnit.SECONDS.sleep(10);
              notEnd = false;
              for (Job job : jobs) {
                  System.out.println("Job Priority : " + job.priority + ", Count : " + job.jobCount);
              }
          }
      
          static class Job implements Runnable {
              private int priority;
              private long jobCount;
      
              public Job(int priority) {
                  this.priority = priority;
              }
      
              @Override
              public void run() {
                  while (notStart) {
                      Thread.yield();
                  }
                  while (notEnd) {
                      Thread.yield();
                      jobCount++;
                  }
              }
          }
      }
      

      運(yùn)行該示例,在筆者機(jī)器上對(duì)應(yīng)的輸出如下

      筆者使用的環(huán)境為:Win10 + JDK11,從輸出可以看到線程優(yōu)先級(jí)起作用了


      線程的狀態(tài)

      Java 線程在運(yùn)行的生命周期中可能處于下表所示的六種不同的狀態(tài),在給定的一個(gè)時(shí)刻,線程只能處于其中的一個(gè)狀態(tài)

      狀態(tài)名稱 說(shuō)明
      NEW 初始狀態(tài),線程被構(gòu)建,但還沒(méi)調(diào)用 start() 方法
      RUNNABLE 運(yùn)行狀態(tài),Java 線程將操作系統(tǒng)中的就緒和運(yùn)行兩種狀態(tài)籠統(tǒng)地稱作“運(yùn)行中”
      BLOCKED 阻塞狀態(tài),表示線程阻塞于鎖
      WAITING 等待狀態(tài),表示線程進(jìn)入等待狀態(tài),進(jìn)入該狀態(tài)表示當(dāng)前線程需要等待其他線程做出一些特定動(dòng)作(通知或中斷)
      TIME_WAITING 超時(shí)等待狀態(tài),該狀態(tài)不同于 WAITING,它是可以在指定的時(shí)間自行返回的
      TERMINATED 終止?fàn)顟B(tài),表示當(dāng)前線程已經(jīng)執(zhí)行完畢

      線程在自身的生命周期中,并不是固定地處于某一狀態(tài),而是隨著代碼的執(zhí)行在不同的狀態(tài)之間進(jìn)行切換


      Daemon 線程

      Daemon 線程是一種支持型線程,主要被用作程序中后臺(tái)調(diào)度以及支持性工作。這意味著,當(dāng)一個(gè) Java 虛擬機(jī)中不存在 Daemon 線程的時(shí)候,Java 虛擬機(jī)將退出??梢哉{(diào)用 Thread.setDaemon(true) 將線程設(shè)置為 Daemon 線程

      使用 Daemon 線程需要注意兩點(diǎn):

      • Daemon 屬性需要在啟動(dòng)線程之前設(shè)置,不能在啟動(dòng)線程之后設(shè)置
      • 在構(gòu)建 Daemon 線程時(shí),不能依靠 finally 塊中的內(nèi)容來(lái)確保執(zhí)行或關(guān)閉清理資源的邏輯。因?yàn)樵?Java 虛擬機(jī)退出時(shí) Daemon 線程中的 finally 塊并不一定會(huì)執(zhí)行

      啟動(dòng)和終止線程

      1. 構(gòu)造線程

      在運(yùn)行線程之前首先要構(gòu)造一個(gè)線程對(duì)象,線程對(duì)象在構(gòu)造的時(shí)候需提供線程需的屬性,如線程所屬的線程組、是否是 Daemon 線程等信息

      2. 啟動(dòng)線程

      線程對(duì)象在初始化完成之后,調(diào)用 start() 方法即可啟動(dòng)線程

      3. 理解中斷

      中斷可以理解為線程的一個(gè)標(biāo)識(shí)位屬性,標(biāo)識(shí)一個(gè)運(yùn)行中的線程是否被其他線程進(jìn)行了中斷操作。中斷好比其他線程對(duì)該線程打了個(gè)招呼,其他線程可以通過(guò)調(diào)用該線程的 interrupt() 方法對(duì)其進(jìn)行中斷操作

      線程通過(guò)檢查自身是否被中斷進(jìn)行響應(yīng),線程通過(guò) isInterrupted() 來(lái)進(jìn)行判斷是否被中斷,也可以調(diào)用靜態(tài)方法 Tread.interrupted() 對(duì)當(dāng)前線程的中斷標(biāo)識(shí)位進(jìn)行復(fù)位。如果線程已經(jīng)處于終結(jié)狀態(tài),即時(shí)線程被中斷過(guò),在調(diào)用該對(duì)象的 isInterrupted() 時(shí)依舊會(huì)返回 false

      許多聲明拋出 InterruptedException 的方法在拋出異常之前,Java 虛擬機(jī)會(huì)先將該線程的中斷標(biāo)識(shí)位清除,然后拋出 InterruptedException,此時(shí)調(diào)用 isInterrupted() 方法將會(huì)返回 false

      在下面的例子中,首先創(chuàng)建兩個(gè)線程 SleepThread 和 BusyThread,前者不停地睡眠,后者一直運(yùn)行,分別對(duì)兩個(gè)線程分別進(jìn)行中斷操作,觀察中斷標(biāo)識(shí)位

      public class Interrupted {
      
          public static void main(String[] args) throws InterruptedException {
              // sleepThread 不停的嘗試睡眠
              Thread sleepThread = new Thread(new SleepRunner(), "SleepThread");
              sleepThread.setDaemon(true);
              // busyThread 不停的運(yùn)行
              Thread busyThread = new Thread(new BusyRunner(), "BusyThread");
              busyThread.setDaemon(true);
              sleepThread.start();
              busyThread.start();
              // 休眠 5 秒,讓 sleepThread 和 busyThread 充分運(yùn)行
              TimeUnit.SECONDS.sleep(5);
              sleepThread.interrupt();
              busyThread.interrupt();
              System.out.println("SleepThread interrupted is " + sleepThread.isInterrupted());
              System.out.println("BusyThread interrupted is " + busyThread.isInterrupted());
              // 防止 sleepThread 和 busyThreaad 立刻退出
              SleepUtils.second(2);
          }
      
          static class SleepRunner implements Runnable {
      
              @Override
              public void run() {
                  while (true) {
                      SleepUtils.second(10);
                  }
              }
          }
      
          static class BusyRunner implements Runnable {
      
              @Override
              public void run() {
                  while (true) {
      
                  }
              }
          }
      }
      

      輸出如下

      從結(jié)果可以看出,拋出 InterruptedException 的線程 SleepThread,其中斷標(biāo)識(shí)位被清除了,而一直忙碌運(yùn)行的線程 BusyThread 的中斷標(biāo)識(shí)位沒(méi)有被清除

      4. 安全地終止線程

      前面提到的中斷操作是一種簡(jiǎn)便的線程間交互方式,適合用來(lái)取消或停止任務(wù)。除了中斷以外,還可以利用一個(gè) boolean 變量來(lái)控制是否需要停止任務(wù)并終止線程

      下面的示例中,創(chuàng)建了一個(gè)線程 CountThread,它不斷地進(jìn)行變量累加,而主線程嘗試對(duì)其進(jìn)行中斷操作和停止操作

      public class Shutdown {
      
          public static void main(String[] args) throws InterruptedException {
              Runner one = new Runner();
              Thread countThread = new Thread(one, "CountThread");
              countThread.start();
              // 睡眠一秒,main 線程對(duì) CountThread 進(jìn)行中斷,使 CountThread 能夠感知中斷而結(jié)束
              TimeUnit.SECONDS.sleep(1);
              countThread.interrupt();
              Runner two = new Runner();
              countThread = new Thread(two, "CountThread");
              countThread.start();
              // 睡眠一秒,main 線程對(duì) Runner two 進(jìn)行中斷,使 CountThread 能夠感知 on 為 false 而結(jié)束
              TimeUnit.SECONDS.sleep(1);
              two.cancel();
          }
      
          private static class Runner implements Runnable {
      
              private long i;
              private volatile boolean on = true;
      
              @Override
              public void run() {
                  while (on && !Thread.currentThread().isInterrupted()) {
                      i++;
                  }
                  System.out.println("Count i = " + i);
              }
      
              public void cancel() {
                  on = false;
              }
          }
      }
      

      main 線程通過(guò)中斷操作和 cancel() 方法均可使 CountThread 得以終止。這種通過(guò)標(biāo)識(shí)位或者中斷操作的方式能夠使線程在終止時(shí)有機(jī)會(huì)去清理資源,而不是武斷地將線程停止,更加安全和優(yōu)雅


        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多