一. 線程的基本概念
1 、入題: 我們大家都知道,我們可以在一臺計(jì)算機(jī)上同時聊天,看電影,下載視頻等,完成上述任務(wù)的各個程序之間是完全相互獨(dú)立的。但是他們在同一段時間內(nèi)又同時處于運(yùn)行狀態(tài)。當(dāng)然呢,它們在這一段時間內(nèi)是分時使用計(jì)算機(jī) CPU 時間的。只不過呢在 CPU 處理速度很快,劃分的時間片段很短,所以給大家感覺上是多個程序在同時運(yùn)行。
2 、進(jìn)程:
進(jìn)程是程序的一次動態(tài)執(zhí)行過程。這個過程包含了從程序代碼從硬盤加載到內(nèi)存、在內(nèi)存中執(zhí)行、執(zhí)行結(jié)束等過程,實(shí)際上也就是進(jìn)程的產(chǎn)生、發(fā)展、消亡的一個過程。
另外,每個進(jìn)程都有自己的獨(dú)立的地址空間和占用的系統(tǒng)資源,在進(jìn)程執(zhí)行結(jié)束后,進(jìn)程會釋放系統(tǒng)資源還給系統(tǒng),供其他程序使用。
3 、線程:
線程是比進(jìn)程更小的一個執(zhí)行單位,它是一段完成特定功能的代碼 。
一個進(jìn)程中可以包含多個線程。
與進(jìn)程不同的是 : 同類線程將共享進(jìn)程的地址空間和系統(tǒng)分配給進(jìn)程的系統(tǒng)資源。線程本身并不占用資源,或者說只占用很少的一部分資源,通常只是寄存器中的數(shù)據(jù)及供程序使用的堆棧等。因此說在同一個進(jìn)程的不同線程之間進(jìn)行切換時,所花費(fèi)的開銷比在進(jìn)程間切換小很多。所以,線程又被稱為輕量級進(jìn)程。
4 、 java 多線程:
一個進(jìn)程中可以同時運(yùn)行多個線程,每個線程執(zhí)行不同的任務(wù)。
5 、多線程的好處:
通過多線程程序設(shè)計(jì),就可以將程序任務(wù)劃分成幾個并行執(zhí)行的子任務(wù),從而提高整個程序的執(zhí)行效率和系統(tǒng)資源的利用率
二. 線程的創(chuàng)建方式
線程 是程序中的執(zhí)行線程。Java 虛擬機(jī)允許應(yīng)用程序并發(fā)地運(yùn)行多個執(zhí)行線程。
每個線程都有一個優(yōu)先級,高優(yōu)先級線程的執(zhí)行優(yōu)先于低優(yōu)先級線程。每個線程都可以或不可以標(biāo)記為一個守護(hù)程序。當(dāng)某個線程中運(yùn)行的代碼創(chuàng)建一個新 Thread 對象時,該新線程的初始優(yōu)先級被設(shè)定為創(chuàng)建線程的優(yōu)先級,并且當(dāng)且僅當(dāng)創(chuàng)建線程是守護(hù)線程時,新線程才是守護(hù)程序。
當(dāng) Java 虛擬機(jī)啟動時,通常都會有單個非守護(hù)線程(它通常會調(diào)用某個指定類的 main 方法)。Java 虛擬機(jī)會繼續(xù)執(zhí)行線程,直到下列任一情況出現(xiàn)時為止:
- 調(diào)用了 Runtime 類的 exit 方法,并且安全管理器允許退出操作發(fā)生。
- 非守護(hù)線程的所有線程都已停止運(yùn)行,無論是通過從對 run 方法的調(diào)用中返回,還是通過拋出一個傳播到 run 方法之外的異常
Thread類的其中的兩個構(gòu)造方法
|
Thread
()
|
實(shí)例一:在Thread子類覆蓋的run方法中編寫運(yùn)行代碼:
public class ThreadTest01 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread thread = new Thread(){
@Override
public void run(){ //覆寫Thread類的run方法
int i = 0;
while(i<5){
try {
//使線程休眠1s,線程由運(yùn)行狀態(tài)進(jìn)入阻塞狀態(tài),阻塞時間單位是毫秒
//sleep()方法是靜態(tài)的,不需要特定的Thread對象就可以調(diào)用它,注意會拋出異常
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("thread:"+Thread.currentThread().getName());//打印當(dāng)前線程的名字
System.out.println("2:"+this.getName());
i++;
}
}
};
//調(diào)用start方法啟動線程:用戶不能直接調(diào)用Thread類中的run方法,而是需要調(diào)用start方法間接調(diào)用run方法。
/* Thread中run方法的definition
public void run() {
if (target != null) {
target.run();
}
}
*/
thread.start();
運(yùn)行結(jié)果:
實(shí)例二:在傳遞給Thread類的Runnable對象的run方法中編寫運(yùn)行代碼
public class ThreadTest01 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread thread = new Thread(){
@Override
public void run(){ //覆寫Thread類的run方法
int i = 0;
while(i<5){
try {
//使線程休眠1s,線程由運(yùn)行狀態(tài)進(jìn)入阻塞狀態(tài),阻塞時間單位是毫秒
//sleep()方法是靜態(tài)的,不需要特定的Thread對象就可以調(diào)用它,注意會拋出異常
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("thread:"+Thread.currentThread().getName());//打印當(dāng)前線程的名字
System.out.println("2:"+this.getName());
i++;
}
}
};
//調(diào)用start方法啟動線程:用戶不能直接調(diào)用Thread類中的run方法,而是需要調(diào)用start方法間接調(diào)用run方法。
/* Thread中run方法的definition
public void run() {
if (target != null) {
target.run();
}
}
*/
thread.start();
Thread thread2 = new Thread(new Runnable(){
@Override
public void run(){ //覆寫Thread類的run方法
int i = 0;
while(i<5){
try {
//使線程休眠1s,線程由運(yùn)行狀態(tài)進(jìn)入阻塞狀態(tài),阻塞時間單位是毫秒
//sleep()方法是靜態(tài)的,不需要特定的Thread對象就可以調(diào)用它,注意會拋出異常
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("thread2:"+Thread.currentThread().getName());//打印當(dāng)前線程的名字
i++;
}
}
});
thread2.start();
}
}
運(yùn)行結(jié)果:
那么大家可以思考這樣兩個問題:
問題一、如果Thread類的run方法被覆寫了,并且為Thread類傳遞的Runnable對象的run方法也編寫了運(yùn)行代碼?那么程序會執(zhí)行哪一個run方法呢?
實(shí)例三:來說明上述問題
public class ThreadTest01 {
/**
* @param args
*/
public static void main(String[] args) {
new Thread(
new Runnable(){
public void run(){ //覆寫Thread類的run方法
int i = 0;
while(i<5){
try {
//使線程休眠1s,線程由運(yùn)行狀態(tài)進(jìn)入阻塞狀態(tài),阻塞時間單位是毫秒
//sleep()方法是靜態(tài)的,不需要特定的Thread對象就可以調(diào)用它,注意會拋出異常
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Runnable:"+Thread.currentThread().getName());//打印當(dāng)前線程的名字
i++;
}
}
}
){
public void run(){ //覆寫Thread類的run方法
int i = 0;
while(i<5){
try {
//使線程休眠1s,線程由運(yùn)行狀態(tài)進(jìn)入阻塞狀態(tài),阻塞時間單位是毫秒
//sleep()方法是靜態(tài)的,不需要特定的Thread對象就可以調(diào)用它,注意會拋出異常
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("thread:"+Thread.currentThread().getName());//打印當(dāng)前線程的名字
i++;
}
}
}.start();
}
}
運(yùn)行結(jié)果為:
總結(jié):在Thread子類的run方法和傳遞給Thread的Runnable對象的run方法都被覆寫的時候,程序執(zhí)行Thread子類的run方法。
問題二:如果Thread類的run方法沒有被覆寫,并且為Thread類傳遞的Runnable對象的run方法也編寫了運(yùn)行代碼?那么程序會執(zhí)行哪一個run方法呢?
總結(jié):顯然是調(diào)用Runnable對象的run方法:實(shí)例二已經(jīng)證明
下一篇將講述Thread的兩種創(chuàng)建方法
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

