開篇說明,有點基礎(chǔ),知道Thread,Runnable如何使用和兩者之間的關(guān)系的可以直接跳過。
先說說Thread和Runnable之間的關(guān)系,簡單到不想多說一句話,看下面代碼:
public class Thread implements Runnable {
...省略,詳細自行查看源代碼...
}
看到以上代碼,應(yīng)該明白了吧。不明白可以看一下總結(jié):Thread類實現(xiàn)Runnable接口,創(chuàng)建一個線程的時候可以使用繼承Thread的方式,但是注意Java是單繼承的,當(dāng)你繼承了Thread你就無法進行其它繼承了。所以,可以也實現(xiàn)Runnable接口的方式,這樣就可以繼承其他類也同時可以實現(xiàn)線程創(chuàng)建。
下面先簡單介紹Thread
//使用繼承Thread的方式,創(chuàng)建一個線程類
public class OneThread extends Thread{
@Override
public void run(){
super.run();
System.out.println("one thread!!!!");
}
}
//再建一個測試類
public class TestThread {
public static void main(String[] args) {
OneThread oneThread = new OneThread();
oneThread.start();
System.out.println("完成!");
}
}
注意到運行結(jié)果沒有?系統(tǒng)可能先打印“完成!”,再打印“one thread!!!!”,按照平時寫單線程來說,應(yīng)該是先打印“one thread!!!!”才對吧。不過這里是多線程,OneThread類創(chuàng)建了一個線程,這個線程里面打印“one thread!!!!”,而打印“完成!”是在主線程上完成的。這也就說明了,使用多線程之后,代碼運行結(jié)果跟調(diào)用順序是無關(guān)的。(“one thread!!!!”這串字符串也有可能先出現(xiàn),反正你理解上面這話就行了)
下面在對以上兩個類進行一下改造,模擬一下cpu執(zhí)行哪個線程是具有不確定性的。
public class OneThread extends Thread{
@Override
public void run(){
try {
for (int i = 0; i < 10; i++) {
int sleepTime = (int) (Math.random()*1000);
Thread.sleep(sleepTime);
System.out.println("one thread!!!!");
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
public class TestThread {
public static void main(String[] args) {
try {
OneThread oneThread = new OneThread();
oneThread.start();
for (int i = 0; i < 10; i++) {
int sleepTime = (int) (Math.random()*1000);
Thread.sleep(sleepTime);
System.out.println("完成!");
}
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
使用一個隨機數(shù),生成一個隨機的掛起時間。從而可以更好地觀察cpu選擇執(zhí)行哪個現(xiàn)場的不確定性。通俗點說一下線程開始執(zhí)行,假如cpu選擇了主線程,然后主線程睡覺1秒鐘,那么在這一秒鐘cpu可能就會選擇其它線程去執(zhí)行,而不會傻X那樣在等主線程,所以此時就會去執(zhí)行了其它線程。大概這樣,不理解可以留言說一下。
上面說了那么多順序的問題。反正一句話說到尾,多線程來說,執(zhí)行順序是不確定的。還有,線程的啟動順序跟執(zhí)行start()方法的順序也沒什么關(guān)系的。start()執(zhí)行的順序不代表線程的啟動順序。在來兩段代碼爽爽唄!??!繼續(xù)搗鼓那兩個類吧。。。懶,新建一個類都不想。
public class OneThread extends Thread{
private int i;
//寫個帶參數(shù)的構(gòu)造方法,主要用來看順序的
public OneThread(int i){
super();
this.i = i;
}
@Override
public void run(){
System.out.println(i);
}
}
public class TestThread {
public static void main(String[] args) {
//如各位所見,下面的start()我按順序排好的。
OneThread o1 = new OneThread(1);
OneThread o2 = new OneThread(2);
OneThread o3 = new OneThread(3);
OneThread o4 = new OneThread(4);
OneThread o5 = new OneThread(5);
OneThread o6 = new OneThread(6);
o1.start();
o2.start();
o3.start();
o4.start();
o5.start();
o6.start();
}
}
運行結(jié)果,絕對不是123456,如果是,那么恭喜你,運氣挺好的。無聊話說太多了。意思基本懂吧。這些都很簡單,甚至有些人看了會不自覺地發(fā)出,哼一聲。
Thread的簡單介紹說到這里,后面還有Runnable的簡單介紹。
通過實現(xiàn)Runnable接口來實現(xiàn)多線程,不廢話,先上一張圖,看看Thread類的構(gòu)造方法,我們上面那些用的基本都是無參的構(gòu)造方法,如下圖,第二個,就是我們即將要用到的構(gòu)造方法:

//創(chuàng)建一個類,實現(xiàn)Runnable接口。
public class OneRunnable implements Runnable {
@Override
public void run() {
System.out.println("one runnable!!!");
}
}
public class TestThread {
public static void main(String[] args) {
//
Runnable runnable = new OneRunnable();
//這里就是用到了上圖的第二個構(gòu)造方法,不用多說吧,就這樣
Thread thread = new Thread(runnable);
thread.start();
System.out.println("完成");
}
}
直接實現(xiàn)Runnable接口這樣解決了Java單繼承這一尷尬!?。。?br> 后面應(yīng)該先簡單一起學(xué)習(xí)下共享數(shù)據(jù)和Thread的幾個方法。
向大家推薦eclipse的vim插件,太好用了。
這里不是廣告,推薦本書《Java多線程核心技術(shù)》-高洪巖,因為我是看著這本書學(xué)習(xí)的。上面的文章是學(xué)習(xí)筆記,并不是用來說教的,不要錯了點什么就噴我。