日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

线程的3种创建方式

發布時間:2025/3/20 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线程的3种创建方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

所有的線程對象都是Thread類或其子類的實例。

1.通過繼承Thread類創建線程類

1.步驟

  • 定義Thread類的子類FirstThread,并重寫run()方法。run()方法的方法體(線程執行體)就是線程要執行的任務。
  • 創建FirstThread類的實例。
  • 調用子類實例的star()方法來啟動線程。
  • 2.代碼:

    public class FirstThread extends Thread{ private int i;//重寫run方法,public void run(){for(;i<1000 ;i++){System.out.println(getName()+" "+i);//之所以可以直接調用Therad類的getName()方法,是因為該類繼承了Thread類}}public static void main(String[] args) {for(int i=0;i<100;i++){//獲取當前線程:這里是主線程 System.out.println("當前線程:"+Thread.currentThread().getName()+" "+i);if(i == 20){//啟動第一個線程new FirstThread().start();//啟動第二個線程new FirstThread().start();}}} }

    部分結果:

    Thread-1 731 Thread-0 16 Thread-1 732 Thread-0 17 Thread-1 733 Thread-0 18 Thread-1 734 Thread-0 19

    3.分析結果

    從結果可以看出,第一個線程與第二個線程在交替運行。而且,我們可以發現,線程1的變量從i從731到734連續,而線程2從16到19連續。這說明,雖然 i 是FirstThread類的實例變量而非局部變量,但因為程序每次創建線程時,都會創建一個對象(new FirstThread),所以線程1與線程2不會共享 i 這個實例變量。
    所以,通過繼承Thread類創建線程類時,多個線程之間無法共享該線程類的實例變量。

    2.實現Runnable接口方式創建線程類

    1.步驟

  • 定義Runnable接口實現類SecondThread類,并重寫該接口的run()方法
  • 創建SecondThread的實例st
  • 以st作為target創建Thread對象,該Thread對象才是真正的線程對象啊,只不過該Thread線程,只負責執行target里的run()方法。
  • 調用線程對象的start()方法啟動。
  • 2.代碼

    public class SecondThread implements Runnable {private int i;@Overridepublic void run() {for(;i<1000;i++){System.out.println(Thread.currentThread().getName()+" "+i);//實現Runnable接口時,只能使用Thread類調用當前線程}}public static void main(String[] args) {SecondThread st = new SecondThread();//創建線程的targetfor(int i=0;i<100;i++){if(i==20){new Thread(st,"線程1").start();new Thread(st, "線程2").start();//兩種方式}}}}

    結果片段1:

    線程1 0 線程2 0 線程2 1 線程2 2 線程2 3 線程2 5 線程2 6

    結果片段2:

    線程2 306 線程2 307 線程1 4 線程1 308 線程1 309

    分析結果

    我們會發現,結果1片段中 i 變量沒有4,而是出現在了片段2中,而且線程2當中沒有i=4這個變量,則線程1就會有,即兩個線程共享 i 這個變量
    所以,程序創建的SecondThread對象只是Thread類構造Thread(Runnable target, String name)中的target,該target可被多個線程共享。

    3.使用Callable和Future創建線程

    Callabled接口有點兒像是Runnable接口的增強版,它以call()方法作為線程執行體,call()方法比run()方法功能更強大。
    call()方法可以有返回值,可以聲明拋出異常類。
    獲取call()方法里的返回值: 通過FutureTask類(實現Future接口)的實例對象的get()方法得到,得到結果類型與創建TutureTask類給的泛型一致。

    1. 步驟

    1、 定義實現Callable接口的實現類,并實現call()方法。注意:Callable有泛型限制,與返回值類型一致。這里是Integer

    public class ThirdThread implements Callable<Integer>{//重寫call()方法}

    2、 再創建Callable實現類的實例tt。

    ThirdThread tt = new ThirdThread();

    3、 使用FutureTask類包裝Callable的實例tt。

    FutureTask<Integer> task = new FutureTask<Integer>(tt);//注意:泛型限制與返回結果一致。

    4、以FutureTask對象(task)作為Thread的target來創建線程,并啟動。

    new Thread(task, "線程").start();

    5、調用FutureTask對象(task)的get()方法獲得返回值

    Integer result = task.get();//會有異常

    2.代碼

    public class ThirdThread implements Callable<Integer>{private int i;@Overridepublic Integer call() throws Exception {for(;i<100;i++){System.out.println(Thread.currentThread().getName()+" "+i);}return i;}public static void main(String[] args) {//創建Callable對象ThirdThread tt = new ThirdThread();FutureTask<Integer> task = new FutureTask<Integer>(tt);for(int i=0;i<1000;i++){System.out.println(Thread.currentThread().getName()+" "+i);if(i == 20){//創建線程 new Thread(task, "線程").start();}}try {//獲取線程返回值Integer result = task.get();System.out.println(result);} catch (InterruptedException e) { e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}}

    3.結果分析

    結果是,只能new一個Thread,即單線程,所以這么寫于多線程是行不通的。需要創建一個能執行多個任務的服務。

    4.Future接口控制Callable里任務的幾個方法

  • boolean cancel(boolean mayInterruptIfRunning) : 試圖取消Callable里的任務,即中斷線程。不一定會成功。
  • V get() : 得到Callable任務里call()方法的返回值 。調用該方法將會導致主線程被主阻塞。必須要等到子線程結束后才會得到返回值得到返回值 后,主線程才能繼續往下執行
  • V get(long timeout,TimeUnit unit) : 也是得到返回值,但該方法會讓程序阻塞timeout和unit指定的時間,若指定時間后還沒有返回值 ,則拋出TimeoutException異常。
  • boolean isCanceled() : 如果在任務結束前被取消了,該方法就會返回true.
  • boolean isDone() : 如果Callalbe任務已完成,則返回true。
  • 5.Callable接口方式的多線程示例

    代碼

    public class CallableAndFuture { public static class MyCallableClass implements Callable { private int i = 0; public Integer call() throws Exception { for(;i<1000;i++){System.out.println(Thread.currentThread().getName()+" "+i);}return i; } } public static void main(String[] args) { // 定義3個Callable類型的任務 MyCallableClass task1 = new MyCallableClass(); MyCallableClass task2 = new MyCallableClass(); MyCallableClass task3 = new MyCallableClass(); // 創建一個執行任務的服務 ExecutorService es = Executors.newFixedThreadPool(3); try { // 提交并執行任務,任務啟動時返回了一個Future對象, // 如果想得到任務執行的結果或者是異??蓪@個Future對象進行操作 Future future1 = es.submit(task1); // 如果調用get方法,當前線程會等待任務執行完畢后才往下執行 // System.out.println("task1: " + future1.get()); Future future2 = es.submit(task2); //System.out.println("task2 cancel: " + future2.cancel(true)); // 獲取第三個任務的輸出,因為執行第三個任務會引起異常 // 所以下面的語句將引起異常的拋出 Future future3 = es.submit(task3); //System.out.println("task3: " + future3.get()); } catch (Exception e) { System.out.println(e.toString()); } // 停止任務執行服務 es.shutdownNow(); } }

    結果片段

    pool-1-thread-2 502 pool-1-thread-3 867 pool-1-thread-2 503 pool-1-thread-3 868 pool-1-thread-2 504 pool-1-thread-3 869 pool-1-thread-2 505 pool-1-thread-3 870 pool-1-thread-2 506 pool-1-thread-3 871 pool-1-thread-2 507

    結果分析
    只要不調用get()方法,就不會阻塞,多個線程之間會交替執行;從序號可看出,每個線程的都是連續的,所以每個線程之間不共享實例變量 i ,這跟Thread方式是一樣的。原因是每個線程我們都new了一個task的。

    4.三種創建方式區別

    首先三種方式都可以創建多線程。
    Thread方式和Callable方式不能共享實例變量;而Runnalbe方式可共享,因為能共享target。
    因為通過實現Runnable接口與Callable接口類似,只是Callable接口方式的call()方法有返回值和可聲明拋出異常,所以我們將這兩種方式統稱為RC方式。通過繼承Thread類方式稱為T方式。

    1. RC方式優缺點:

  • 優點
  • 還可以繼承其他類。
  • 多個線程可共享一個target對象。適用于多個線程處理同一份資源的情況。
  • 缺點
    編程稍稍復雜些。
  • 2. T方式優缺點:

  • 優點
    編程簡單。

  • 缺點
    因為單繼承的限制,不能再繼承其他類了。

  • 綜上分析:最好采用RC方式。

    總結

    以上是生活随笔為你收集整理的线程的3种创建方式的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。