第一種方式:繼承Thread類安全
步驟:一、定義類繼承Thread多線程
二、覆寫Threa類的run方法。 自定義代碼放在run方法中,讓線程運行函數
三、調用線程的star方法,this
該線程有兩個做用:啓動線程,調用run方法。spa
代碼示例:線程
1 class Test extends Thread 2 { 3 //private String name; 4 Test(String name) 5 { 6 //this.name = name; 7 super(name); 8 } 9 public void run() 10 { 11 for(int x=0; x<60; x++) 12 { 13 System.out.println((Thread.currentThread()==this)+"..."+this.getName()+" run..."+x); //Thread.currentThread():獲取當前線程對象 14 } 15 } 16 17 } 18 19 20 class ThreadTest 21 { 22 public static void main(String[] args) 23 { 24 Test t1 = new Test("one---"); 25 Test t2 = new Test("two+++"); 26 t1.start(); 27 t2.start(); 28 // t1.run(); 29 // t2.run(); 30 31 for(int x=0; x<60; x++) 32 { 33 System.out.println("main....."+x); 34 } 35 } 36 }
第二種方式:實現Runnable接口code
步驟:一、定義類實現Runnable接口對象
二、覆蓋Runnable接口中的run方法,運行的代碼放入run方法中。blog
三、經過Thread類創建線程對象。繼承
四、將Runnable接口的子類對象做爲實際參數傳遞給Thread類的構造函數。
由於,自定義的run方法所屬的對象是Runnable接口的子類對象。因此要讓線程去指定指定對象的run方法。就必須明確該run方法所屬對象
五、調用Thread類的start方法開啓線程並調用Runnable接口子類的run方法
代碼示例:賣票程序,多個窗口同時賣票
1 class Ticket implements Runnable 2 { 3 private int tick = 100; 4 public void run() 5 { 6 while(true) 7 { 8 if(tick>0) 9 { 10 System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--); 11 } 12 } 13 } 14 } 15 16 17 class TicketDemo 18 { 19 public static void main(String[] args) 20 { 21 22 Ticket t = new Ticket(); 23 24 Thread t1 = new Thread(t);//建立了一個線程; 25 Thread t2 = new Thread(t);//建立了一個線程; 26 Thread t3 = new Thread(t);//建立了一個線程; 27 Thread t4 = new Thread(t);//建立了一個線程; 28 t1.start(); 29 t2.start(); 30 t3.start(); 31 t4.start(); 32 } 33 }
兩種方式的區別:
第二種方式好處:避免了單繼承的侷限性。好比當一個student類繼承了person類,再需繼承其餘的類時就不能了,因此在定義線程時,建議使用第二種方式。
解決多線程安全性問題:一、同步代碼塊
二、同步函數:鎖爲this
三、靜態同步函數: 鎖爲Class對象:類名.class