<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Java 線程創(chuàng)建與常用方法

      進(jìn)程與線程

      進(jìn)程

      • 程序由指令和數(shù)據(jù)組成,但這些指令要運(yùn)行,數(shù)據(jù)要讀寫,就必須將指令加載至 CPU,數(shù)據(jù)加載至內(nèi)存。在指令運(yùn)行過(guò)程中還需要用到磁盤、網(wǎng)絡(luò)等設(shè)備。進(jìn)程就是用來(lái)加載指令、管理內(nèi)存、管理 IO 的
      • 當(dāng)一個(gè)程序被運(yùn)行,從磁盤加載這個(gè)程序的代碼至內(nèi)存,這時(shí)就開(kāi)啟了一個(gè)進(jìn)程

      線程

      • 一個(gè)進(jìn)程之內(nèi)可以分為一到多個(gè)線程。
      • 一個(gè)線程就是一個(gè)指令流,將指令流中的一條條指令以一定的順序交給 CPU 執(zhí)行
      • Java 中,線程作為最小調(diào)度單位,進(jìn)程作為資源分配的最小單位。 在 windows 中進(jìn)程是不活動(dòng)的,只是作為線程的容器

      進(jìn)程與線程的區(qū)別

      • 進(jìn)程基本上相互獨(dú)立的,而線程存在于進(jìn)程內(nèi),是進(jìn)程的一個(gè)子集
      • 進(jìn)程擁有共享的資源,如內(nèi)存空間等,供其內(nèi)部的線程共享
      • 進(jìn)程間通信較為復(fù)雜
        • 同一臺(tái)計(jì)算機(jī)的進(jìn)程通信稱為 IPC(Inter-process communication)
        • 不同計(jì)算機(jī)之間的進(jìn)程通信,需要通過(guò)網(wǎng)絡(luò),并遵守共同的協(xié)議,例如 HTTP
      • 線程通信相對(duì)簡(jiǎn)單,因?yàn)樗鼈児蚕磉M(jìn)程內(nèi)的內(nèi)存,一個(gè)例子是多個(gè)線程可以訪問(wèn)同一個(gè)共享變量
      • 線程更輕量,線程上下文切換成本一般上要比進(jìn)程上下文切換低

      并行與并發(fā)

      單核 cpu 下,線程實(shí)際還是 串行執(zhí)行 的。操作系統(tǒng)中有一個(gè)組件叫做任務(wù)調(diào)度器,將 cpu 的時(shí)間片(windows下時(shí)間片最小約為 15 毫秒)分給不同的程序使用,只是由于 cpu 在線程間(時(shí)間片很短)的切換非常快,人類感覺(jué)是 同時(shí)運(yùn)行的 。總結(jié)為一句話就是: 微觀串行,宏觀并行 。一般會(huì)將這種 線程輪流使用 CPU 的做法稱為并發(fā) (concurrent)

      多核 cpu下,每個(gè) 核(core) 都可以調(diào)度運(yùn)行線程,這時(shí)候線程可以是并行的。

      Java 線程

      創(chuàng)建和運(yùn)行線程

      • 直接使用 Thread

        package create;
        
        
        import lombok.extern.slf4j.Slf4j;
        
        @Slf4j(topic = "c.ThreadCre")
        public class ThreadCre {
            public static void main(String[] args) {
        
                Thread t = new Thread(){
                    @Override
                    public void run() {
                        log.debug("running");
                    }
                };
        
                t.start();
        
                log.debug("running");
        
            }
        }
        
      • 使用 Runnable 配合 Thread

        package create;
        
        import lombok.extern.slf4j.Slf4j;
        
        @Slf4j(topic = "c.RunnableCre")
        public class RunnableCre {
            public static void main(String[] args) {
                Runnable r = new Runnable() {
                    @Override
                    public void run() {
                        log.debug("running");
                    }
                };
        
                Thread t = new Thread(r,"t2");
        
                t.start();
            }
        }
        

        使用 lambda 方式簡(jiǎn)化

        package create;
        
        import lombok.extern.slf4j.Slf4j;
        
        @Slf4j(topic = "c.RunnableCre")
        public class RunnableCre {
            public static void main(String[] args) {
                Runnable r = () -> { log.debug("running"); };
        
                Thread t = new Thread(r,"t2");
        
                t.start();
            }
        }
        
      • FutureTask 配合 Thread

        package create;
        
        import lombok.extern.slf4j.Slf4j;
        
        import java.util.concurrent.Callable;
        import java.util.concurrent.ExecutionException;
        import java.util.concurrent.FutureTask;
        
        @Slf4j(topic = "c.FutureTaskCre")
        public class FutureTaskCre {
            public static void main(String[] args) throws ExecutionException, InterruptedException {
                FutureTask<Integer> task = new FutureTask<>(new Callable<Integer>() {
                    @Override
                    public Integer call() throws Exception {
                        log.debug("running...");
                        Thread.sleep(1000);
                        return 100;
                    }
                });
        
                Thread t = new Thread(task,"t1");
                t.start();
        
                log.debug("{}",task.get());
            }
        }
        

      Thread 與 Runnable 的關(guān)系

      • 用 Runnable 更容易與線程池等高級(jí) API 配合
      • 用 Runnable 讓任務(wù)類脫離了 Thread 繼承體系,更靈活

      線程運(yùn)行的原理

      棧與棧幀

      每個(gè)線程啟動(dòng)后,虛擬機(jī)就會(huì)為其分配一塊棧內(nèi)存。

      • 每個(gè)棧由多個(gè)棧幀(Frame)組成,對(duì)應(yīng)著每次方法調(diào)用時(shí)所占用的內(nèi)存
      • 每個(gè)線程只能有一個(gè)活動(dòng)棧幀,對(duì)應(yīng)著當(dāng)前正在執(zhí)行的那個(gè)方法

      線程上下文切換

      因?yàn)橐韵乱恍┰驅(qū)е?cpu 不再執(zhí)行當(dāng)前的線程,轉(zhuǎn)而執(zhí)行另一個(gè)線程的代碼

      • 線程的 cpu 時(shí)間片用完
      • 垃圾回收
      • 有更高優(yōu)先級(jí)的線程需要運(yùn)行
      • 線程自己調(diào)用了 sleep、yield、wait、join、park、synchronized、lock 等方法

      當(dāng) Context Switch 發(fā)生時(shí),需要由操作系統(tǒng)保存當(dāng)前線程的狀態(tài),并恢復(fù)另一個(gè)線程的狀態(tài),Java 中對(duì)應(yīng)的概念就是程序計(jì)數(shù)器(Program Counter Register),它的作用是記住下一條 jvm 指令的執(zhí)行地址,是線程私有的

      • 狀態(tài)包括程序計(jì)數(shù)器、虛擬機(jī)棧中每個(gè)棧幀的信息,如局部變量、操作數(shù)棧、返回地址等
      • Context Switch 頻繁發(fā)生會(huì)影響性能

      常見(jiàn)方法

      方法名 static 功能說(shuō)明 注意
      start() 啟動(dòng)一個(gè)新線程,在新的線程運(yùn)行 run 方法中的代碼 start 方法只是讓線程進(jìn)入就緒,里面的代碼不一定立刻運(yùn)行(CPU的時(shí)間片還沒(méi)有分給它)。每個(gè)線程對(duì)象的 start 方法只能調(diào)用一次,否則會(huì)出現(xiàn)異常
      run() 新線程啟動(dòng)后會(huì)調(diào)用的方法 如果在構(gòu)造 Thread 對(duì)象時(shí)傳遞了 Runnable 參數(shù),則線程啟動(dòng)后會(huì)調(diào)用 Runnable 中的 run 方法。但可以創(chuàng)建 Thread 的子類對(duì)象來(lái)覆蓋默認(rèn)行為
      join() 等待線程運(yùn)行結(jié)束
      join(long n) 等待線程運(yùn)行結(jié)果,最多等待 n 毫秒
      getId() 獲取線程長(zhǎng)整型的 id
      getName() 獲取線程名
      setName(String) 修改線程名
      getPriority() 獲取線程優(yōu)先級(jí)
      setPriority(int) 修改線程優(yōu)先級(jí) java中規(guī)定線程優(yōu)先級(jí)是1~10 的整數(shù),較大的優(yōu)先級(jí)能提高該線程被 CPU 調(diào)度的機(jī)率
      getState() 獲取線程狀態(tài) Java 中線程狀態(tài)是用 6 個(gè) enum 表示,分別為:NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
      isInterrupted() 判斷是否被打斷 不會(huì)清除 打斷標(biāo)記
      isAlive() 線程是否存活(還沒(méi)有運(yùn)行完畢)
      interrupt() 打斷線程 如果被打斷線程正在 sleep,wait,join 會(huì)導(dǎo)致被打斷的線程拋出 InterruptedException,并清除 打斷標(biāo)記 ;如果打斷的正在運(yùn)行的線程,則會(huì)設(shè)置 打斷標(biāo)記 ;park 的線程被打斷,也會(huì)設(shè)置 打斷標(biāo)記
      interrupted() static 判斷當(dāng)前線程是否被打斷 會(huì)清除 打斷標(biāo)記
      currentThread() static 獲取當(dāng)前正在執(zhí)行的線程
      sleep(long n) static 讓當(dāng)前執(zhí)行的線程休眠 n 毫秒,休眠時(shí)讓出 CPU 的時(shí)間片給其他程序
      yield() static 提示線程調(diào)度器讓出當(dāng)前線程對(duì)CPU的使用 主要是為了測(cè)試和調(diào)試

      start 與 run

      調(diào)用 run

      public static void main(String[] args) {
       	Thread t1 = new Thread("t1") {
       		@Override
       		public void run() {
       			log.debug(Thread.currentThread().getName());
       			FileReader.read(Constants.MP4_FULL_PATH);
       		}
       	};
          
       	t1.run();
       	log.debug("do other things ...");
      }
      

      輸出

      19:39:14 [main] c.TestStart - main
      19:39:14 [main] c.FileReader - read [1.mp4] start ...
      19:39:18 [main] c.FileReader - read [1.mp4] end ... cost: 4227 ms
      19:39:18 [main] c.TestStart - do other things ...
      

      程序仍在 main 線程運(yùn)行, FileReader.read() 方法調(diào)用還是同步的

      總結(jié)

      • 直接調(diào)用 run 是在主線程中執(zhí)行了 run,沒(méi)有啟動(dòng)新的線程
      • 使用 start 是啟動(dòng)新的線程,通過(guò)新的線程間接執(zhí)行 run 中的代碼

      sleep 與 yield

      sleep

      • 調(diào)用 sleep 會(huì)讓當(dāng)前線程從 Running 進(jìn)入 Timed Waiting 狀態(tài)(阻塞)
      • 其它線程可以使用 interrupt 方法打斷正在睡眠的線程,這時(shí) sleep 方法會(huì)拋出 InterruptedException
      • 睡眠結(jié)束后的線程未必會(huì)立刻得到執(zhí)行(搶占時(shí)間片)
      • 建議用 TimeUnit 的 sleep 代替 Thread 的 sleep 來(lái)獲得更好的可讀性

      yield

      • 調(diào)用 yield 會(huì)讓當(dāng)前線程從 Running 進(jìn)入 Runnable 就緒狀態(tài),然后調(diào)度執(zhí)行其它線程
      • 具體的實(shí)現(xiàn)依賴于操作系統(tǒng)的任務(wù)調(diào)度器

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

      • 線程優(yōu)先級(jí)會(huì)提示(hint)調(diào)度器優(yōu)先調(diào)度該線程,但它僅僅是一個(gè)提示,調(diào)度器可以忽略它
      • 如果 cpu 比較忙,那么優(yōu)先級(jí)高的線程會(huì)獲得更多的時(shí)間片,但 cpu 閑時(shí),優(yōu)先級(jí)幾乎沒(méi)作用

      join

      等待一個(gè)線程執(zhí)行結(jié)束

      等待多個(gè)線程的結(jié)果

      情況一:

      package testJoin;
      
      import lombok.extern.slf4j.Slf4j;
      
      @Slf4j(topic = "c.demo1")
      public class demo1 {
      
          static int r = 0 , r1 = 0 , r2 = 0;
      
          public static void main(String[] args) throws InterruptedException {
              test2();
          }
      
          private static void test2() throws InterruptedException {
              Thread t1 = new Thread(() -> {
                  try {
                      Thread.sleep(1000);
                      r1 = 10;
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              });
              Thread t2 = new Thread(() -> {
                  try {
                      Thread.sleep(2000);
                      r1 = 20;
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              });
              long start = System.currentTimeMillis();
              t1.start();
              t2.start();
              log.debug("join begin");
              t1.join();
              log.debug("t1 join end");
              t2.join();
              log.debug("t2 join end");
              long end = System.currentTimeMillis();
              log.debug("r1: {} r2: {} cost: {}",r1,r2,end-start);
          }
      }
      

      輸出:

      14:18:02 [main] c.demo1 - join begin
      14:18:03 [main] c.demo1 - t1 join end
      14:18:04 [main] c.demo1 - t2 join end
      14:18:04 [main] c.demo1 - r1: 20 r2: 0 cost: 2008
      

      情況二:

      package testJoin;
      
      import lombok.extern.slf4j.Slf4j;
      
      @Slf4j(topic = "c.demo1")
      public class demo1 {
      
          static int r = 0 , r1 = 0 , r2 = 0;
      
          public static void main(String[] args) throws InterruptedException {
              test2();
          }
      
          private static void test2() throws InterruptedException {
              Thread t1 = new Thread(() -> {
                  try {
                      Thread.sleep(1000);
                      r1 = 10;
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              });
              Thread t2 = new Thread(() -> {
                  try {
                      Thread.sleep(2000);
                      r1 = 20;
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              });
              long start = System.currentTimeMillis();
              t1.start();
              t2.start();
              log.debug("join begin");
              t2.join();
              log.debug("t2 join end");
              t1.join();
              log.debug("t1 join end");
              long end = System.currentTimeMillis();
              log.debug("r1: {} r2: {} cost: {}",r1,r2,end-start);
          }
      }
      

      輸出:

      14:19:19 [main] c.demo1 - join begin
      14:19:21 [main] c.demo1 - t2 join end
      14:19:21 [main] c.demo1 - t1 join end
      14:19:21 [main] c.demo1 - r1: 20 r2: 0 cost: 2006
      

      另外 join 也可以帶參數(shù),是有時(shí)效的等待。當(dāng)?shù)皆O(shè)定時(shí)間線程還未給出結(jié)果,直接向下運(yùn)行,不再等待。如果設(shè)定時(shí)間還沒(méi)到但是線程已經(jīng)執(zhí)行完畢,則直接向下執(zhí)行,不再等待。

      interrupt

      打斷 sleep,wait,join 的線程

      這幾個(gè)方法都會(huì)讓線程進(jìn)入阻塞狀態(tài)

      打斷 sleep 的線程, 會(huì)清空打斷狀態(tài),以 sleep 為例

      package testInterrupt;
      
      import lombok.extern.slf4j.Slf4j;
      
      @Slf4j(topic = "c.demo1")
      public class demo1 {
          public static void main(String[] args) throws InterruptedException {
              Thread t1 = new Thread(() -> {
                  log.debug("sleep...");
                  try {
                      Thread.sleep(5000);
                      //注意:sleep,wait,join等被打斷并以異常形式表現(xiàn)出來(lái)后
                      // 會(huì)把打斷標(biāo)記重新置為 false(未打斷狀態(tài))
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              },"t1");
      
              t1.start();
              Thread.sleep(1000);
              log.debug("interrupt");
              t1.interrupt();
              log.debug("打斷標(biāo)記:{}",t1.isInterrupted());
          }
      }
      

      輸出:

      15:08:12 [t1] c.demo1 - sleep...
      15:08:13 [main] c.demo1 - interrupt
      15:08:13 [main] c.demo1 - 打斷標(biāo)記:false
      java.lang.InterruptedException: sleep interrupted
      	at java.lang.Thread.sleep(Native Method)
      	at testInterrupt.demo1.lambda$main$0(demo1.java:11)
      	at java.lang.Thread.run(Thread.java:748)
      
      Process finished with exit code 0
      

      打斷正常運(yùn)行的線程打斷標(biāo)記置為:true

      package testInterrupt;
      
      import lombok.extern.slf4j.Slf4j;
      
      @Slf4j(topic = "c.demo2")
      public class demo2 {
          public static void main(String[] args) throws InterruptedException {
              Thread t1 = new Thread(() -> {
                  while (true){
                      boolean interrupted = Thread.currentThread().isInterrupted();
                      if(interrupted){
                          log.debug("被打斷了,退出循環(huán)");
                          break;
                      }
                  }
              },"t1");
              t1.start();
      
              Thread.sleep(1000);
              log.debug("interrupt");
              t1.interrupt();
          }
      }
      

      輸出:

      15:17:40 [main] c.demo2 - interrupt
      15:17:40 [t1] c.demo2 - 被打斷了,退出循環(huán)
      

      打斷 park 線程

      package testInterrupt;
      
      import lombok.extern.slf4j.Slf4j;
      
      import java.util.concurrent.locks.LockSupport;
      
      @Slf4j(topic = "c.demo4")
      public class demo4 {
          public static void main(String[] args) throws InterruptedException {
              Thread t1 = new Thread(() -> {
                  log.debug("park...");
                  LockSupport.park();
                  log.debug("unpark...");
                  log.debug("打斷狀態(tài):{}",Thread.currentThread().isInterrupted());
              },"t1");
      
              t1.start();
      
              Thread.sleep(1000);
              t1.interrupt();
          }
      }
      

      輸出:

      14:16:21 [t1] c.demo4 - park...
      14:16:22 [t1] c.demo4 - unpark...
      14:16:22 [t1] c.demo4 - 打斷狀態(tài):true
      

      兩階段終止模式

      package testInterrupt;
      
      import lombok.extern.slf4j.Slf4j;
      
      @Slf4j(topic = "c.demo3")
      public class demo3 {
          public static void main(String[] args) throws InterruptedException {
              TwoPhaseTermination tpt = new TwoPhaseTermination();
              tpt.start();
              Thread.sleep(3500);
              tpt.stop();
          }
      }
      
      @Slf4j(topic = "c.TwoPhaseTermination")
      class TwoPhaseTermination{
          private Thread monitor;
      
          //啟動(dòng)監(jiān)控線程
          public void start(){
              monitor = new Thread(() -> {
                  while (true){
                      Thread current = Thread.currentThread();
                      if(current.isInterrupted()){
                          log.debug("料理后事");
                          break;
                      }
                      try {
                          Thread.sleep(1000);//情況1
                          log.debug("執(zhí)行監(jiān)控記錄");//情況2
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                          //重新設(shè)置打斷標(biāo)記
                          current.interrupt();
                      }
                  }
              });
      
              monitor.start();
          }
      
          //終止監(jiān)控線程
          public void stop(){
      
              monitor.interrupt();
          }
      }
      

      輸出:

      15:33:02 [Thread-0] c.TwoPhaseTermination - 執(zhí)行監(jiān)控記錄
      15:33:03 [Thread-0] c.TwoPhaseTermination - 執(zhí)行監(jiān)控記錄
      15:33:04 [Thread-0] c.TwoPhaseTermination - 執(zhí)行監(jiān)控記錄
      java.lang.InterruptedException: sleep interrupted
      	at java.lang.Thread.sleep(Native Method)
      	at testInterrupt.TwoPhaseTermination.lambda$start$0(demo3.java:29)
      	at java.lang.Thread.run(Thread.java:748)
      15:33:04 [Thread-0] c.TwoPhaseTermination - 料理后事
      
      Process finished with exit code 0
      

      不推薦的方法

      還有一些不推薦使用的方法,這些方法已過(guò)時(shí),容易破壞同步代碼塊,造成線程死鎖

      方法名 static 功能說(shuō)明
      stop() 停止線程運(yùn)行
      suspend() 掛起(暫停)線程運(yùn)行
      resume() 恢復(fù)線程運(yùn)行
      posted @ 2022-06-04 14:28  染沁  閱讀(402)  評(píng)論(3)    收藏  舉報(bào)
      主站蜘蛛池模板: 成av人片一区二区久久| 亚洲成av人片无码不卡播放器| 国产人与zoxxxx另类| 嫩草欧美曰韩国产大片| 人妻蜜臀久久av不卡| 国产成人高清亚洲综合| 亚洲欧洲av一区二区久久| 极品vpswindows少妇| 亚洲欧洲日产国码久在线| 国产亚洲精品久久久久久无亚洲| 少妇办公室好紧好爽再浪一点| 国产v亚洲v天堂无码久久久| 国产福利视频区一区二区| 国产精品福利一区二区久久| 不卡一区二区三区四区视频| AV秘 无码一区二| 国产午夜亚洲精品国产成人| 久久a级片| 成年美女黄网站色大片免费看| 华池县| 亚洲精品无码av天堂| 亚洲成色精品一二三区| 国产精品国产三级国快看| 国产最大成人亚洲精品| 91精品国产色综合久久不| 亚欧乱色精品免费观看| 亚洲中文字幕一区二区| 亚洲の无码国产の无码步美| 中文国产成人久久精品小说| 成人做受120秒试看试看视频 | 年日韩激情国产自偷亚洲| 九九热精品免费视频| 国产91丝袜在线观看| 国产精品高清视亚洲精品| 99久久国产综合精品女图图等你| 亚洲精品一区二区美女| 乱码午夜-极品国产内射| 久久一亚色院精品全部免费| 日韩精品一区二区亚洲av| 亚洲真人无码永久在线| 天堂俺去俺来也www色官网|