1. 程式人生 > >執行緒(十一)兩種傳統傳統方式建立:(thread、Runnable), 執行緒池方式ExcutorServicePool

執行緒(十一)兩種傳統傳統方式建立:(thread、Runnable), 執行緒池方式ExcutorServicePool

傳統方式建立執行緒:

1、繼承Thread類,重寫run方法

2、實現Runnable介面,覆蓋介面中的run方法,然後將介面實現扔給Thread

run方法探祕:

Thread原始碼中的run方法,如下:

@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

由程式碼知道,run方法中是一個if判斷,target不為空,就可以執行 target.run()

target是什麼??

private Runnable target;

由程式碼知,target就是一個Runnable介面。

最後,進入Runnable程式碼:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

Runnable中原來還是run方法;

我自己的理解為:Thread方法實現run方法要經歷一個if語句的判斷,直接不要if判斷了,直接重寫run; 而Runnable,直接呼叫重寫run即可

總結:為什麼建立執行緒有兩種方式?

第一種:你不是要先進行if判斷麼?我現在不判斷了,我把你的if幹掉,我在run()方法中自己寫程式碼,想幹啥就幹啥,即重寫Thread中的run()方法,;

第二種:你不是要先進行if判斷麼?行,給你一個Runnable介面讓你判斷,但你還是得呼叫我Runnable中的run()方法啊,那我重寫我Runnable中的run()方法不就行了! 

1、Thread建立執行緒(繼承Thread)

(1)繼承Thread,呼叫run方法

(2)start()開啟執行緒

public static void main(String[] args){
   Thread thread1 = new Thread(){
      @Override
      public void run(){
          try {
                    Thread.sleep(500);//讓執行緒休息500毫秒
               } catch (InterruptedException e) {
                    e.printStackTrace();
               }
           System.out.println(Thread.currentThread().getName());//打印出當前執行緒名
      }
   };
   
   thread1.start();
}

2、Runnable建立執行緒(實現Runnable介面)

(1)實現Runnable介面,呼叫run方法

(2)start()開啟執行緒

public static void main(String[] args){
    Thread thread2 = new Thread(new Runnable(){
           @Override
           public void run(){
              try(){
                  Thread.sleep(1000);
              } catch(Exception e){
                  e.printStackTrace();
              }
            System.out.println(Thread.currentThread().getName());  //讓執行緒休息500毫秒
​
           }
      });
​
   thread2.start();
}

3、Thread和Runnable同時建立執行緒

public static void main(String[] args){
      new Thread(new Runnable(){//實現runnable介面
           @Override
           public void run(){
              try(){
                  Thread.sleep(1000);
              } catch(Exception e){
                  e.printStackTrace();
              }
            System.out.println("Runnable:" + Thread.currentThread().getName());  //讓執行緒休息500毫秒
​
           }
      }){ //實現thread   
         @Override
         public void run(){
          try {
                    Thread.sleep(500);//讓執行緒休息500毫秒
               } catch (InterruptedException e) {
                    e.printStackTrace();
               }
           System.out.println("Thread:" + Thread.currentThread().getName());//打印出當前執行緒名
         }
      }.start();
}

經過執行發現,執行的是Thread中的run方法。

總結:

執行start()後,肯定先在子類中找run()方法,找到了,父類的run()方法自然就被幹掉了,所以會打印出Thread:,如果我們現在假設子類中沒有重寫run()方法,那麼必然要去父類找run()方法,父類的run()方法中就得判斷是否有Runnable傳進來,現在有一個,所以執行Runnable中的run()方法,那麼就會列印Runnable:出來。

4、ExcutorServicePool執行緒池方法,建立執行緒

private ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
​
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");  //沒有精確到毫秒
​
    public  void scheduledStatusNotify() {
        ScheduledFuture<?> future = pool.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
            ..........
           }
      });
    }

執行緒池的方式建立執行緒本質上還是通過第二種方法(Runnable介面),重寫run方法