Java總結--多線程與併發1

總覽

  • Java中的進程和線程
    • 運行一個程序會產生一個進程,進程包含至少一個線程(主線程
    • 每個進程對應一個JVM實例,多個線程共享JVM裏的堆
    • 主線程可以創建子線程,主線程原則上要後於子線程完成執行(各種關閉動作在主線程中執行

java線程(Thread)

  • Thread的start()run()

    • 調用start()會創建一個新的子進程並啓動,run()只是Threa對象的普通方法調用
      在這裏插入圖片描述
      在這裏插入圖片描述
      在這裏插入圖片描述
      在這裏插入圖片描述
      注:由源碼可得,start()會創建一個線程,然後去執行run()方法裏的內容
    • Java線程創建關係圖
      在這裏插入圖片描述
  • ThreadRunnable

    • Thread是類,Runnable是接口
    • Thread類實現了Runnable接口
    • Runnable只有一個抽象run()方法(Runnable不具有多線程的特性在這裏插入圖片描述
      在這裏插入圖片描述
  • java線程的創建

    1. 繼承Thread類,並重寫run()方法(線程中的邏輯在run()方法中實現
      public class MyThread extends Thread {
          private String name;
          public MyThread(String name){
              this.name = name;
          }
          @Override
          public void run(){
              for(int i = 0 ; i < 10 ; i ++){
                  System.out.println("Thread start : " + this.name + ",i= " + i);
              }
          }
      }
      
      public class ThreadDemo {
          public static void main(String[] args) {
              MyThread mt1 = new MyThread("Thread1");
              mt1.start();
          }
      }
      
    2. 實現Runnable接口
      原理:Thread帶參構造函數中,可以傳遞Runnable,且調用Threadrun()方法會調用Runnable中的run()方法
      在這裏插入圖片描述
      在這裏插入圖片描述
      public class MyRunnable implements Runnable {
          private String name;
          public MyRunnable(String name){
              this.name = name;
          }
          @Override
          public void run(){
              for(int i = 0 ; i < 10 ; i ++){
                  System.out.println("Thread start : " + this.name + ",i= " + i);
              }
          }
      }
      
      public class RunnableDemo {
          public static void main(String[] args) throws InterruptedException {
              MyRunnable mr1 = new MyRunnable("Runnable1");
              Thread t1 = new Thread(mr1);
              t1.start();
          }
      }
      
    • 補充:給run()方法傳參
      • 構造方法傳參
      • 成員變量傳參
      • 回調函數傳參
  • java線程返回值的處理

    • 主線程等待法
      Thread.currentThread().sleep(500);
      
    • 使用Thread類的join()阻塞當前線程以等待子線程處理完畢
      public class CycleWait implements Runnable{
          private String value;
          public void run() {
              try {
                  Thread.currentThread().sleep(5000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              value = "we have data now";
          }
      
          public static void main(String[] args) throws InterruptedException {
              CycleWait cw = new CycleWait();
              Thread t = new Thread(cw);
              t.start();
      //        while (cw.value == null){
      //            Thread.currentThread().sleep(100);
      //        }
              t.join();
              System.out.println("value : " + cw.value);
          }
      }
      
    • 通過Callable接口實現:通過FutureTask 或者線程池獲取
      • FutureTask
        注:FutureTask實現了Runnable
        在這裏插入圖片描述
      • 判斷Callable中的call方法是否執行完畢 在這裏插入圖片描述
      • call方法執行完畢,則返回,否則阻塞當前進程
        在這裏插入圖片描述
      • 帶參get,增加了超時機制
        在這裏插入圖片描述
        //實現callable
        public class MyCallable implements Callable<String> {
            @Override
            public String call() throws Exception{
                String value="test";
                System.out.println("Ready to work");
                Thread.currentThread().sleep(5000);
                System.out.println("task done");
                return  value;
            }
        }
        //通過FutureTask完成等待
        public class FutureTaskDemo {
            public static void main(String[] args) throws ExecutionException, InterruptedException {
                FutureTask<String> task = new FutureTask<String>(new MyCallable());
                new Thread(task).start();
                if(!task.isDone()){
                    System.out.println("task has not finished, please wait!");
                }
                System.out.println("task return: " + task.get());
            }
        }
        
        //通過線程池等待
        public class ThreadPoolDemo {
            public static void main(String[] args) {
                ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
                Future<String> future = newCachedThreadPool.submit(new MyCallable());
                if(!future.isDone()){
                    System.out.println("task has not finished, please wait!");
                }
                try {
                    System.out.println(future.get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } finally {
                    newCachedThreadPool.shutdown();
                }
            }
        }
        
    • sleepwait方法
      • sleep
        • sleepThread類的方法
        • 可以在任何地方調用
        • sleep方法只會讓出CPU,不會釋放鎖
      • wait
        • waitObject類中定義的方法
        • 只能在synchronized方法或synchronized塊中使用
        • wait方法會讓出CPU,也會釋放已經佔有的同步鎖
      public class WaitSleepDemo {
          public static void main(String[] args) {
              final Object lock = new Object();
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      System.out.println("thread A is waiting to get lock");
                      synchronized (lock){
                          try {
                              System.out.println("thread A get lock");
                              Thread.sleep(20);
                              System.out.println("thread A do wait method");
                              lock.wait();
                              System.out.println("thread A is done");
                          } catch (InterruptedException e){
                              e.printStackTrace();
                          }
                      }
                  }
              }).start();
              try{
                  Thread.sleep(10);
              } catch (InterruptedException e){
                  e.printStackTrace();
              }
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      System.out.println("thread B is waiting to get lock");
                      synchronized (lock){
                          try {
                              System.out.println("thread B get lock");
                              System.out.println("thread B is sleeping 10 ms");
                              Thread.sleep(10);
                              lock.notifyAll();
                              Thread.yield();
                              Thread.sleep(2000);
                              System.out.println("thread B is done");
                          } catch (InterruptedException e){
                              e.printStackTrace();
                          }
                      }
                  }
              }).start();
      
          }
      }
      
    • 線程的中斷
      • 調用interrupt()通知線程中斷
        在這裏插入圖片描述
      • 線程中應該做的處理
        在這裏插入圖片描述
        public class InterruptDemo {
            public static void main(String[] args) throws InterruptedException {
                Runnable interruptTask = new Runnable() {
                    @Override
                    public void run() {
                        int i = 0;
                        try {
                            //在正常運行任務時,經常檢查本線程的中斷標誌位,如果被設置了中斷標誌就自行停止線程
                            while (!Thread.currentThread().isInterrupted()) {
                                Thread.sleep(100); // 休眠100ms
                                i++;
                                System.out.println(Thread.currentThread().getName() + " (" + Thread.currentThread().getState() + ") loop " + i);
                            }
                        } catch (InterruptedException e) {
                            //在調用阻塞方法時正確處理InterruptedException異常。(例如,catch異常後就結束線程。)
                            System.out.println(Thread.currentThread().getName() + " (" + Thread.currentThread().getState() + ") catch InterruptedException.");
                        }
                    }
                };
                Thread t1 = new Thread(interruptTask, "t1");
                System.out.println(t1.getName() +" ("+t1.getState()+") is new.");
        
                t1.start();                      // 啓動“線程t1”
                System.out.println(t1.getName() +" ("+t1.getState()+") is started.");
        
                // 主線程休眠300ms,然後主線程給t1發“中斷”指令。
                Thread.sleep(300);
                t1.interrupt();
                System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
        
                // 主線程休眠300ms,然後查看t1的狀態。
                Thread.sleep(300);
                System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
            }
        }
        
    • 線程狀態圖
      在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章