Java基礎之多線程(二)

Java多線程實現方式主要有四種:繼承Thread類、實現Runnable接口、實現Callable接口經過FutureTask包裝器來建立Thread線程、使用ExecutorService、Callable、Future實現有返回結果的多線程。html

其中前兩種方式線程執行完後都沒有返回值,後兩種是帶返回值的。 java

使用Thread對象的interrupt()方法,打斷線程睡眠則會拋出interrupted異常git

System.in.read();讀取鍵盤輸入多線程

方式一:繼承Thread類(線程沒有返回值,在java.lang包中less

  重寫run()方法,調用start()方法執行。ide

  須要注意的是:爲何多線程的啓動不是調用run()方法,而是調用start()方法?函數

      在Java開發中有一門JNI(Java Native Interface)技術,這門技術的特色,使用Java調用本機操做系統的函數,可是這個技術不能離開特定的操做系統。測試

若是線程想要執行,須要操做系統分配資源。因此此操做嚴格來說須要JVM根據不一樣的操做系統來實現的。this

  start()方法中,使用了native關鍵字修飾了方法,而native關鍵字時根據不一樣的操做系統分配不一樣的資源。url

  start()方法,不單單要啓動多線程執行的代碼,還須要根據不一樣的操做系統來分配資源

1 package test; 2 3 public class MyThread { 4 public static void main(String[] args) { 5 Test t1 = new Test("one"); 6 Test t2 = new Test("two"); 7 Test t3 = new Test("three"); 8 /** 9 * 調用Thread類中的start方法,才能進行多線程的操做,而不是run方法 10 * start()方法不單單啓動多線程代碼的執行,還須要根據不一樣的操做系統分配資源 11 */ 12 try {//調用Thread類中的sleep方法,讓線程等待指定的一段時間 13 Thread.sleep(1000); 14 } catch (InterruptedException e) { 15  e.printStackTrace(); 16  } 17  t1.start(); 18  t2.start(); 19  t3.start(); 20  } 21 } 22 23 /** 24 * 繼承線程類Thread,重寫run()方法,在run方法中實現須要進行的數據操做 25 * @author Administrator 26 * 27 */ 28 class Test extends Thread{ 29 30 private String name; 31 32 public Test(String name) { 33 this.name=name; 34  } 35  @Override 36 public void run() {//須要進行多進程的操做 37 for (int i = 0; i < 100; i++) { 38 System.out.println(name+"===>"+i); 39  } 40  } 41 }

 方式二:實現Runnable接口(線程沒有返回值,在java.lang包中)

  該接口標註爲:@Java.lang.FactionInterface

    實現run方法,將Runnable對象做爲參數放入到Thread構造方法中,在調用start()方法。

1 package test; 2 /** 3 * 測試Runnable接口 4 * @author Administrator 5 * 6 */ 7 public class MyRunnable { 8 public static void main(String[] args) { 9 Demo mr1 = new Demo("A"); 10 Demo mr2 = new Demo("B"); 11 Demo mr3 = new Demo("C"); 12 //將該對象做爲參數,傳入到Thread類中,在調用start()方法。 13 new Thread(mr1).start(); 14 new Thread(mr2).start(); 15 new Thread(mr3).start(); 16  } 17 } 18 19 /** 20 * 實現Runnable接口,實現多線程 21 * @author Administrator 22 * 23 */ 24 class Demo implements Runnable { 25 26 private String name; 27 28 public Demo(String name) { 29 this.name = name; 30  } 31 32  @Override 33 public void run() { 34 for (int i = 0; i < 300; i++) { 35 System.out.println(name + "==>" + i); 36  } 37  } 38 39 }

問題一:Thread與Runnable有什麼不一樣?

  一、Thread實現了Runnable接口,使用Runnable接口能夠避免單根繼承的問題。

  二、Runnable接口實現的多線程能夠比Thread類實現的多線程更加清楚的描述數據共享的概念。

問題二:寫出兩種多線程實現操做?

1 package test; 2 /** 3 * Runnable接口比Thread類更加清楚的描述了數據共享的概念 4 * @author Administrator 5 * 6 */ 7 public class ThreadAndRunnable { 8 9 public static void main(String [] args){ 10 TestDemo1 t = new TestDemo1(); 11 new Thread(t).start(); 12 new Thread(t).start(); 13 new Thread(t).start(); 14 try { 15 Thread.sleep(2000); 16 } catch (InterruptedException e) { 17 // TODO Auto-generated catch block 18  e.printStackTrace(); 19  } 20 System.out.println("=======================================我是分割線======================================="); 21 /** 22 * 這裏雖然也能夠數據共享, 23 * 可是,TestDemo2已經繼承了Thread類,而這裏又要new三個Thread類出來, 24 * 區調用start方法,顯得畫蛇添足 25 */ 26 TestDemo2 d1 = new TestDemo2(); 27 new Thread(d1).start(); 28 new Thread(d1).start(); 29 new Thread(d1).start(); 30  } 31 32 } 33 34 /** 35 * 實現了Runnable接口的類,能夠明顯的表示出數據共享的概念 36 * @author Administrator 37 * 38 */ 39 class TestDemo1 implements Runnable{ 40 /** 41 * 買票 42 */ 43 private int numb = 20; 44 45  @Override 46 public void run() { 47 for (int i = 0; i < 200; i++) { 48 if (this.numb > 0) { 49 System.out.println("買票;numb = "+this.numb--); 50  } 51  } 52  } 53 } 54 55 /** 56 * Thread類實現數據共享 57 * @author Administrator 58 * 59 */ 60 class TestDemo2 extends Thread{ 61 private int num = 20; 62  @Override 63 public void run() { 64 for (int i = 0; i < 200; i++) { 65 if(this.num > 0) 66 System.out.println("買票;num = "+this.num--); 67  } 68  } 69 70 }

 

方式三:實現Callable接口經過FutureTask包裝器來建立Thread線程(線程有返回值,該接口在java.util.concurrent包中)

1 @java.lang.FactionalInterface 2 public interface Callable<V>{ 3 public V call() throws Exception; 4 }

從JDK1.5開始提供一個類java.util.concurrentFutureTask<V>,這個類主要負責Callable接口對象操做的,該類的定義結構爲:

1 public class FutureTask<V> extends Object implements RunnableFuture<V>
 2 
 3 //然而RunnableFuture有是什麼?
 4 public interface RunnableFuture<V> extends Runnable,Future<V>
 5 
 6 //然而FutureTask<V>接口的構造方法內,接受了Callable接口對象
 7 public FutureTask(Callable<V> callable) 8 //接受callable對象的目的:取得call()方法的結果,只有經過FutureTask類才能獲得返回的 //結果
1 package test; 2 3 import java.util.concurrent.Callable; 4 import java.util.concurrent.FutureTask; 5 /** 6 * Callable接口實現多線程實例,能夠獲得返回的數據 7 * @author Administrator 8 * 9 */ 10 public class MyCllable { 11 12 public static void main(String[] args) throws Exception{ 13 TestDemo t1 = new TestDemo(); 14 TestDemo t2 = new TestDemo(); 15 FutureTask<String> task1 =new FutureTask<String>(t1); 16 FutureTask<String> task2 =new FutureTask<String>(t2); 17 /** 18 * FutureTask類是Runnable接口子類,因此能夠做爲構造參數調用start()方法 19 */ 20 new Thread(task1).start();//啓動多線程 21 new Thread(task2).start();//啓動多線程 22 System.out.println("task1===>"+task1.get());//獲得返回的結果 23 System.out.println("task2===>"+task2.get());//獲得返回的結果 24  } 25 26 } 27 28 class TestDemo implements Callable<String>{ 29 30 private int num = 20; 31 32  @Override 33 public String call() throws Exception { 34 for (int i = 0; i < 200; i++) { 35 if(this.num > 0){ 36 System.out.println("使用Callable接口實現多線程:"+num--); 37  } 38  } 39 return "數據歸零"; 40  } 41 42 }

示例:寫一個線程類輸出001—999啓動10條線程同時執行該類,每一個線程要都有機會,並且不能重複而其有序

 1 package com.zelin.lesson.test;  2 
 3 import java.text.NumberFormat;  4 
 5 /**
 6  * 編寫一個線程類,啓動10條線程同時執行該類,要求輸出效果以下所示  7  *    001  8  * 002  9  * 003 10  * …. 11  * 999 12  * 輸出001—999 每一個線程要都有機會,並且不能重複而其有序 13  */
14 public class TestThread { 15     public static void main(String[] args) { 16         Thread0 t = new Thread0(); 17         for (int i = 0; i < 10; i++) { 18             new Thread(t).start(); 19  } 20  } 21 } 22 
23 class Thread0 implements Runnable{ 24     //1.定義變量
25     private int tickets = 1; 26  @Override 27     public void run() { 28         while(true){ 29             synchronized (this){ 30                 if(tickets == 1000)  break; 31                 //2.將變量進行格式化處理
32                 NumberFormat numberFormat = NumberFormat.getInstance(); 33                 //3.設置輸出的數字的最小整數位數
34                 numberFormat.setMinimumIntegerDigits(3); 35                 //4.對數字進行格式化處理
36                 String format = numberFormat.format(tickets++); 37                 //5.輸出
38  System.out.println(format); 39  } 40  } 41  } 42 }

     線程(三)點我

相關文章
相關標籤/搜索