<small id="7ktuj"></small>
      <bdo id="7ktuj"></bdo>
        <mark id="7ktuj"></mark>

        <source id="7ktuj"></source>
        <small id="7ktuj"></small>

        ITPub博客

        首頁 > 應用開發 > Java > JAVA中線程的創建

        JAVA中線程的創建

        原創 Java 作者:蝴蝶飛啊飛 時間:2019-11-06 14:10:03 0 刪除 編輯

        一、線程(Thread)

        1. 線程

        線程:是指程序中的順序流

        多線程:一個程序中的多個順序流同時執行

        (1) 線程的狀態:

        新生

        就緒

        運行

        阻塞

        終止

        (2) 學習多線程:

        1) 線程的創建

        2) 線程的狀態

        3) 線程的安全

        4) 線程的通信

        2. 線程的創建

        1) 繼承 Thread ,重寫 run() 方法

        (1) run() 方法中定義線程體

        (2) 開啟:使用 start() 方法開啟線程

        // 繼承 Tread

        public class Thread01 extends Thread{

        // 重寫 run() 方法

        // 多線程的線程體

        @Override

        public void run() {

        for(int i=1;i<=20;i++){

        System.out.println(" 一邊敲代碼 ...");

        }

        }

        public static void main(String[] args) {

        // 開啟多線程 創建線程

        Thread01 th=new Thread01();

        // 開啟線程

        th.start();

        //th.run();    注意 : 這是方法的調用 , 不是多線程的開啟

        for(int i=1;i<=20;i++){

        System.out.println(" 一邊聊天 ...");

        }

        }

        }

        2) 實現 Runnable 接口,重寫 run() 方法(推薦使用,線程安全)

        開啟:通過外匯返傭http://www.kaifx.cn/Tread 類中的 start() 方法開啟線程

        優點: (1) 避免了單繼承的局限性

        (2) 實現資源的共享

        public class Thread02 implements Runnable{

        // 定義線程體的方法 , 當被調用的時候 , 會逐行執行里面的代碼

        @Override

        public void run() {

        for(int i=1;i<=100;i++){

        System.out.println(" 一邊敲代碼 ...");

        }

        }

        public static void main(String[] args) {

        Thread02 th=new Thread02();

        // 開啟線程 // 創建線程

        Thread t=new Thread(th);  // 因為開啟線程的方法在 Thread 類中 ,Thread 做為代理類出現

        t.start();

        for(int i=1;i<=100;i++){

        System.out.println(" 一邊聊天 ...");

        }

        }

        }

        實現資源共享:

        /*

         * 模擬鐵路 12306

         * 需求: 100 張票 ,3 個人買完

         * 資源共享: 100 張票

         */

        public class Thread03 implements Runnable{

        // 成員 資源

        int tikets=100;

        @Override

        public synchronized void run() {

        // 循環買票

        while(true){

        if(tikets<=0){

        break;

        }

        // 捕捉異常

        //static void   sleep(long millis) 在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),此操作受到系統計時器和調度程序精度和準確性的影響

        try {

        Thread.sleep(100);  // 線程睡眠 100ms

        } catch (InterruptedException e) {

        e.printStackTrace();

        }

        //static Thread    currentThread() 返回對當前正在執行的線程對象的引用

        //String     getName() 返回該線程的名稱

        System.out.println(Thread.currentThread().getName()+" 正在購買第 "+tikets--);

        }

        }

        public static void main(String[] args) {

        Thread03 th=new Thread03 ();

        // 開啟三個線程

        Thread th1=new Thread(th," 張三 ");

        Thread th2=new Thread(th," 李四 ");

        Thread th3=new Thread(th," 王五 ");

        th1.start();

        th2.start();

        th3.start();

        }

        }

        3) 實現 Callable 接口,重寫 call() 方法,方法中定義線程體(了解)

        優點:可以拋出異常,可以有返回值

        // 導包

        import java.util.concurrent.Callable;

        import java.util.concurrent.ExecutionException;

        import java.util.concurrent.ExecutorService;

        import java.util.concurrent.Executors;

        import java.util.concurrent.Future;

        // 實現 Callable 接口   <> 可以添加泛型,引用類型的數據

        public class Race05 implements Callable<Integer>{

        // 存儲贏的人的名字

        String winner=null;

        // 重寫 call() 方法,方法中定義線程體

        @Override

        public Integer call() throws Exception {

        // 開始游戲 , 循環停止游戲結束

        for(int i=1;i<=100;i++){

        if(" 兔子 ".equals(Thread.currentThread().getName()) && i%10==0){

        try {

        Thread.sleep(2);

        } catch (InterruptedException e) {

        e.printStackTrace();

        }

        }

        System.out.println(Thread.currentThread().getName()+" 正在跑第 "+i+" ");

        // 調用有 Boolean 類型返回值的結束方法

        boolean flag=over(i);

        // 判斷返回值是 true ,或為 false

        if(flag){

        return i;

        }

        }

        return -1;

        }

        /**

         * @param steps   當前線程的步數

         * 返回值 : 如果有人贏了返回 true, 否則返回 false

         */

        public boolean over(int steps){

        if(winner!=null){

        return true;

        }else{

        if(steps==100){

        winner=Thread.currentThread().getName();

        return true;

        }

        return false;

        }

        }

        public static void main(String[] args) throws InterruptedException, ExecutionException {

        Race05 race=new Race05();

        //1. 創建執行服務

        ExecutorService server=Executors.newFixedThreadPool(2);

        //2. 提交執行

        Future result1=server.submit(race);

        Future result2=server.submit(race);

        //3. 獲取結果

        Integer i1=(Integer) result1.get();

        Integer i2=(Integer) result2.get();

        System.out.println(i1+"---->"+i2);

        //4. 關閉服務

        server.shutdown();

        }

        }

        2. 線程狀態問題

        1) 狀態:

        新生狀態: new

        就緒狀態: start() 線程就會進入到就緒狀態 , 線程會進入到就緒隊列 , 等待 CPU 的調度

        運行狀態:

        阻塞狀態: 非常執行完畢 , 通過程序進行控制

        終止狀態:

        注意: 一個線程一旦進入到終止狀態 , 沒有辦法恢復了 , 就算是重寫 new 一個線程 , 也不剛那個線程了,一個線程一旦進入到阻塞狀態 , 無法直接恢復到運行 , 等待阻塞接觸之后恢復到就緒狀態

        2) 如何進入到就緒狀態

        1 start()

        2 )阻塞解除

        3 )線程切換,被切換的線程進入到就緒狀態

        4 yield() 禮讓線程

        3) 如何進入到阻塞狀態

        1 sleep() 方法

        2 join()

        3 wait()

        4) 如何讓一個線程進入到終止狀態

        1 )正常執行完畢

        2 destroy() |stop() 已過時

        3 )通過標識手動判斷

        3.Thread 類的方法學習

        1 sleep() 線程休眠

        1. 模擬網絡延遲

        2. 放大問題的可能性

        注意:sleep() 線程的休眠是抱著資源不放進行休眠,同步的是對象資源,讓出的是 CPU 的資源

        // 實現 Runnable 接口

        public class State01 implements Runnable{

        public static void main(String[] args) {

         new Thread(new State01()).start();

        }

        /*

         * 倒計時   10 9 8 7 6 5 4 3 2 1

         * 重寫 run() 方法

         */

        @Override

        public void run() {

        for(int i=10;i>=0;i--){

        // 模擬網絡延遲

        try {

        Thread.sleep(1000);   //sleep() 線程的休眠 1000ms=1s

        } catch (InterruptedException e) {

        e.printStackTrace();

        }

        if(i==0){

        System.out.println(" 過年好 ...");

        break;

        }

        System.out.println(i);

        }

        }

        }

        2 yield() 禮讓線程

        static Thread   currentThread()  

        返回對當前正在執行的線程對象的引用

        String   getName()  

        返回該線程的名稱

        //static void     yield() 暫停當前正在執行的線程對象,并執行其他線程

        public class Yield03 implements Runnable{

        public static void main(String[] args) {

        new Thread(new Yield03(),"A").start();

        new Thread(new Yield03(),"B").start();

        }

        @Override

        public void run() {

        System.out.println(Thread.currentThread().getName()+"start...");

        //yield() 禮讓線程,等待 CPU 的再度調用,但是是隨機分配

        Thread.yield();  // 靜態方法

        System.out.println(Thread.currentThread().getName()+"end...");

        }

        }

        3 getState() 方法

        Thread.State  getState()

          返回該線程的狀態

        void  setPriority(int newPriority)

        更改線程的優先級

        /*

         * getState() 方法

         * 線程的優先級: 提高優先執行的可能性 , 但是不一定就會先執行

         * void setPriority(int newPriority) 更改線程的優先級。

         * 優先級分為1~10 1 最小   10 最大

         * Thread.NORM_PRIORITY 5 ( 默認為 5)

         * Thread.MAX_PRIORITY  10

         * Thread.MIN_PRIORITY  1

         */

        public class GetState04 {

        public static void main(String[] args) {

        Thread th=new Thread(()->{

        for(int i=1;i<=10;i++){

        try {

        Thread.sleep(100);

        } catch (InterruptedException e) {

        e.printStackTrace();

        }

        System.out.println(" 一邊學習 ...");

        }

        });

        th.setPriority(Thread.NORM_PRIORITY);

        System.out.println(th.getPriority());

        System.out.println(th.getState());//NEW

        th.start();

        System.out.println(th.getState());//RUNNABLE

        for(int i=1;i<=10;i++){

        if(i==5){

        try {

        Thread.sleep(500);

        } catch (InterruptedException e) {

        e.printStackTrace();

        }

        }

        System.out.println(th.getState());

        }

        try {

        Thread.sleep(1000);

        } catch (InterruptedException e) {

        // TODO Auto-generated catch block

        e.printStackTrace();

        }

        System.out.println(th.getState());

        if(th.getState()== Thread.State.TERMINATED){

        System.out.println(" 終止 ");

        }

        }

        }

        4 join() 合并線程,插隊線程

        void join()

               等待該線程終止。

         void join(long millis)

               等待該線程終止的時間最長為 millis 毫秒。

        void join(long millis, int nanos)

               等待該線程終止的時間最長為 millis 毫秒 + nanos 納秒

        /*

         * join() 合并線程 , 插隊線程

        模擬:父親讓兒子去買煙的過程

         */

        public class JoinDemo05 {

        public static void main(String[] args) {

        new Thread(new Father()).start();

        }

        }

        class Father implements Runnable{

        @Override

        public void run() {

        System.out.println(" 想抽煙 ...");

        System.out.println(" 給兒子錢,讓兒子去買煙 ..");

        Thread th=new Thread(new Son());

        th.start();

        try {

        th.join();// 合并線程

        } catch (InterruptedException e) {

        e.printStackTrace();

        System.out.println(" 兒子丟了 , 趕緊去找兒子 ..");

        }

        System.out.println(" 接過煙 , 吸一口 , ~");

        }

        }

        class Son  implements Runnable{

        @Override

        public void run() {

        System.out.println(" 接過前 , 給老爸去買煙 ...");

        System.out.println(" 路邊有個電玩城 , 進去玩 10s...");

        for(int i=1;i<=10;i++){

        try {

        Thread.sleep(1000);

        } catch (InterruptedException e) {

        e.printStackTrace();

        }

        System.out.println(i+"s...");

        }

        System.out.println(" 趕緊去買煙 ...");

        System.out.println(" 把煙給老爸 , 前揣兜里 ...");

        }

        }

        4. 線程安全

        多個線程同時操作同一個資源的時候, 才可能會出現線程安全問題

        1 synchronized 關鍵字

        通過同步synchronized 關鍵字控制線程安全 :

        同步方法

        靜態方法

        成員方法

        同步塊 synchronized ( |this| 資源 ){ 代碼 }

        : 類名 .class 一個類的 Class 對象 一個類只有一個 Class 對象

        // 通過同步 synchronized 關鍵字控制線程安全

        public class Single01 {

        public void main(String[] args) {

        new Thread(()->{System.out.println(Single.newInstance());}).start();;

        new Thread(()->{System.out.println(Single.newInstance());}).start();;

        }

        }

        class Single{

        //2. 私有的靜態的該類的引用

        private static Single single=null;

        //1. 構造器私有話

        private Single(){}

        //3. 公共的靜態的方法

        // 在方法上添加鎖 , 鎖方法

        /*public static synchronized Single newInstance(){

        if(single==null){

        single=new Single();

        }

        return single;

        }*/

        // 同步塊

        /*public static Single newInstance(){

        synchronized (Single.class) {  // 控制多線程排隊執行

        if(single==null){

        single=new Single();

        }

        }  //{} 中的代碼就是排隊執行的代碼

        return single;

        }*/

        public static Single newInstance(){

        if(single==null){

        //A B C

        synchronized (Single.class) {  // 控制多線程排隊執行

        // 雙重檢查 double check

        if(single==null){

        single=new Single();

        }

        }  //{} 中的代碼就是排隊執行的代碼

        }

        return single;

        }

        }


        來自 “ ITPUB博客 ” ,鏈接:http://www.ep4tq.com/69946279/viewspace-2662888/,如需轉載,請注明出處,否則將追究法律責任。

        上一篇: Mustache要點總結
        下一篇: java框架之mybatis
        請登錄后發表評論 登錄
        全部評論
        管他誰是誰非,做自己的主宰,我是這條街最亮的崽!

        注冊時間:2019-08-22

        • 博文量
          49
        • 訪問量
          21835
        妹子图每日分享