線程:
方式一:繼承Thread類并且復(fù)寫run方法.
格式:
class MyThread extends Thread
{
public void run()
{
線程中要運(yùn)行的代碼.
}
}
其步驟為:
1.定義類繼承Thread類.
2.復(fù)習(xí)run方法.---->目的是:用于存儲(chǔ)線程中要運(yùn)行的代碼,將自定義的代碼存儲(chǔ)在run方法中,讓線程運(yùn)行.
3.調(diào)用線程的start方法
注意:不是調(diào)用run方法.
線程的名字:一般線程有默認(rèn)的名字,形式為:Thread-編號(hào),編號(hào)是從0開始標(biāo)記的.
也可以獲取當(dāng)前運(yùn)行線程的名字,用方法:Thread.currentThread().getName()
Thread.currentThread() 是用于獲取當(dāng)前線程的對(duì)象.(靜態(tài)的).
自定義設(shè)置線程的名字可以用setName()或者構(gòu)造函數(shù)來(lái)設(shè)置.
有關(guān)線程的繼承方式的代碼實(shí)例和練習(xí):

1 /* 2 線程:步驟: 3 1.定義一個(gè)類繼承Thread 4 2.復(fù)寫類中的潤(rùn)方法 5 3.創(chuàng)建一個(gè)對(duì)象(創(chuàng)建一個(gè)對(duì)象也就創(chuàng)建了一個(gè)線程) 6 4.調(diào)用線程的start()方法,調(diào)用start方法后,啟動(dòng)了線程,同時(shí)也調(diào)用了run()方法. 7 */ 8 class MyThread extends Thread //第一步 9 {10 public void run() //第二步11 {12 for(int x = 0; x < 60; x++)13 System.out.View Code
1 /* 2 3 */ 4 class FirstThread extends Thread 5 { 6 //private String name; 7 FirstThread(String name) 8 { 9 //this.name = name;10 super(name); 11 }12 public void run()13 {14 for(int i = 1; i <= 50; i++)15 {16 //System.out.println(this.name+"FirstThread run.====="+i);17 System.out.println((Thread.currentThread()==this)+"......"+this.getName()+"FirstThread run.====="+i);18 }19 }20 }21 22 class ThreadTest23 {24 public static void main(String args[])25 {26 FirstThread ft1 = new FirstThread("First===");27 FirstThread ft2 = new FirstThread("Second===");28 ft1.start();29 ft2.start();30 31 for(int i = 1; i <= 50; i++)32 {33 System.out.println("mainThread run.====="+i);34 }35 }36 }View Code 1 /* 2 售票窗口例子: 3 多個(gè)窗口能夠同時(shí)賣票. 4 */ 5 6 class Ticket extends Thread 7 { 8 private static int ticket = 100; //不用static時(shí)候.兩個(gè)窗口都會(huì)同時(shí)賣同號(hào)的票,即100張票連個(gè)窗口都會(huì)賣一次(相當(dāng)于賣了200次) 9 Ticket(String name)10 {11 super(name);12 }13 public void run()14 {15 while(true)16 {17 if(ticket>0)18 {19 System.out.println(Thread.currentThread().getName()+"===賣票===="+ticket--);20 }21 }22 }23 }24 25 26 class TicketDemo27 {28 public static void main(String args[])29 {30 Ticket t1 = new Ticket("窗口1");31 Ticket t2 = new Ticket("窗口2");32 t1.start();33 t2.start();34 35 }36 }線程的第二種方式:
實(shí)現(xiàn)Runnable接口:
格式為:
class MyRunnable implements Runnable
{
public void run()
{
線程中要運(yùn)行的有關(guān)代碼.
}
}
其步驟一般為:
1.定義一個(gè)類實(shí)現(xiàn)Runnable接口.
2.復(fù)寫Runnable接口中的run方法.
3.通過(guò)Thread類來(lái)創(chuàng)建一個(gè)對(duì)象.
4.將Runnable的子類的對(duì)象作為實(shí)際參數(shù)傳給Thread類中的構(gòu)造函數(shù).
5.調(diào)用Thread類中的start方法.開啟線程,并調(diào)用Runnable接口的子類的run方法.(可以理解為run方法又start方法開啟調(diào)用的)
例如:
class MyRunnable implements Runnable //步驟1
{
public void run() //步驟2
{
S.o.p();
}
}
class RunnableDemo
{
p.s.v.main()
{
MyRunnable mr = new MyRunnable();
Thread t1 = new Thread(mr); //步驟3---4
t1.start(); //步驟5
}
}

1 /* 2 售票窗口例子: 3 多個(gè)窗口能夠同時(shí)賣票. 4 不使用靜態(tài)的ticket來(lái)完成每個(gè)窗口的賣票,且不會(huì)賣重復(fù)的票. 5 通過(guò)實(shí)現(xiàn)Runnable接口來(lái)完成. 6 7 創(chuàng)建線程的第二種方法: 8 實(shí)現(xiàn)Runnable接口來(lái)完成. 9 步驟:10 1.定義一個(gè)類實(shí)現(xiàn)(implements)Runnable接口11 2.復(fù)寫Runnable接口中的run方法12 3.通過(guò)Thread類來(lái)創(chuàng)建對(duì)象13 4.將Runnable接口的子類對(duì)象作為實(shí)際參數(shù)傳給Thread類中的構(gòu)造函數(shù).14 5.調(diào)用Thread類中的start方法開啟線程,并調(diào)用Runnable接口的子類的run方法.15 */16 17 18 class Ticket implements Runnable19 {20 private int ticket = 100; // private static int ticket = 100; 21 /*22 由于Ticket并未繼承Thread,該類并沒(méi)有g(shù)etName()的方法,因此是不能調(diào)用的.23 Ticket(String name)24 {25 super(name);26 }27 */28 public void run()29 {30 while(true)31 {32 if(ticket>0)33 {34 System.out.println(Thread.currentThread().getName()+"===賣票====="+ticket--);35 }36 }37 }38 }39 40 41 class RunnableTicketDemo42 {43 public static void main(String args[])44 {45 Ticket t = new Ticket(); //t是共享數(shù)據(jù).46 47 /*48 下面的方法不靜態(tài)ticket時(shí)候會(huì)出現(xiàn)賣了200張票的情況,如何不靜態(tài) ticket =100,也自定義線程名且不出現(xiàn)賣200張票的情況????49 */50 //Ticket tt = new Ticket();51 //Ticket ttt = new Ticket();52 //Ticket tttt = new Ticket();53 54 //Thread t1 = new Thread(t,"窗口1");55 //Thread t2 = new Thread(tt,"窗口2");56 //Thread t3 = new Thread(ttt,"窗口3");57 //Thread t4 = new Thread(tttt,"窗口4");58 /*59 下面的代碼執(zhí)行后,Thread.currentThread().getName()獲取的是默認(rèn)的線程名.60 */61 Thread t1 = new Thread(t);62 Thread t2 = new Thread(t);63 Thread t3 = new Thread(t);64 Thread t4 = new Thread(t);65 66 t1.start();67 t2.start();68 t3.start();69 t4.start();70 }71 }View Code繼承方式和實(shí)現(xiàn)方式的多態(tài)的區(qū)別和特點(diǎn):
實(shí)現(xiàn)方式:避免了單繼承的局限性.一般定義線程時(shí),建議使用實(shí)現(xiàn)方式.
區(qū)別:
1.繼承Thread:線程代碼存放在Thread的子類的run方法中.
2.實(shí)現(xiàn)Runnabel:線程的代碼存放在Runnable接口的子類的run方法中.
最后是同步代碼塊,解決了多線程的安全性問(wèn)題
格式為:
synchronized(對(duì)象)
{
需要被同步的代碼塊.
}
有關(guān)實(shí)現(xiàn)Runnable接口和同步的示例和練習(xí)代碼:
1 /* 2 多線程的安全問(wèn)題; 3 打印出了票數(shù)為0.-1.-2等問(wèn)題. 4 5 問(wèn)題分析,多條語(yǔ)句同時(shí)使用同一線程的共享數(shù)據(jù)時(shí),一個(gè)線程只執(zhí)行了一部分,還未執(zhí)行完,另一個(gè)線程就參與進(jìn)來(lái)執(zhí)行了,導(dǎo)致共享數(shù)據(jù)的錯(cuò)誤. 6 在if判斷中,當(dāng)ticket=1時(shí),一個(gè)線程進(jìn)去執(zhí)行語(yǔ)句后,另一個(gè)線程也執(zhí)行進(jìn)來(lái). 7 此時(shí)的ticket已經(jīng)通過(guò)ticket--變成了0,從而導(dǎo)致了輸出票數(shù)為0或者負(fù)數(shù)的情況. 8 解決方案: 9 對(duì)操作多條共享數(shù)據(jù)的語(yǔ)句,讓一個(gè)線程完全執(zhí)行完畢后才讓另一個(gè)線程執(zhí)行,從而避免這種問(wèn)題的發(fā)生.10 11 同步代碼塊.關(guān)鍵字:synchronized12 格式:13 synchronized(對(duì)象)14 {15 需要被同步的代碼.16 {17 18 同步的條件:19 1.必須是多線程,單線程不能用同步.20 2.必須是多個(gè)線程使用同一個(gè)鎖.21 必須保證同步中只有一個(gè)線程在運(yùn)行.22 23 同步的好處:解決了多線程的安全性問(wèn)題.24 缺點(diǎn):每個(gè)線程都要判斷鎖,影響程序運(yùn)行速度,耗費(fèi)資源.25 */26 class Ticket implements Runnable27 {28 private int ticket = 100; 29 Object obj = new Object();30 public void run()31 {32 while(true)33 {34 synchronized(obj) //obj相當(dāng)于鎖.35 {36 if(ticket>0)37 {38 // try{Thread.sleep(10);}catch(Exception e){}39 System.out.println(Thread.currentThread().getName()+"===賣票====="+ticket--);40 }41 }42 }43 }44 }45 46 class RunnableTicketSafeDemo47 {48 public static void main(String args[])49 {50 Ticket t = new Ticket(); //t是共享數(shù)據(jù).51 52 Thread t1 = new Thread(t);53 Thread t2 = new Thread(t);54 Thread t3 = new Thread(t);55 Thread t4 = new Thread(t);56 57 t1.start();58 t2.start();59 t3.start();60 t4.start();61 }62 }
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注