多線程
進(jìn)程和線程
進(jìn)程
進(jìn)程:是正在運(yùn)行的程序
-
是系統(tǒng)進(jìn)行資源分配和調(diào)用的獨(dú)立單位
-
每個(gè)進(jìn)程都具有它自己的存儲(chǔ)空間和系統(tǒng)資源
線程
線程:是進(jìn)程中的單個(gè)順序控制流,是一條執(zhí)行路徑
-
單線程:一個(gè)進(jìn)程如果只有一條執(zhí)行路徑,則稱之為單線程程序
-
多線程:一個(gè)進(jìn)程如果有多條執(zhí)行路徑,則稱之為多線程程序
繼承Thread類方式實(shí)現(xiàn)多線程
-
繼承 Thread 類
-
定義一個(gè) MyThread 繼承 Thread 類
-
在 MyThread 類中重寫 run() 方法
-
創(chuàng)建 MyThread 類的對(duì)象
-
啟動(dòng)線程
demo:
定義一個(gè)名字為MyThread的類繼承Thread類,重新里面的run方法
package com.itxs.demo01;
/**
* @Classname : MyThread
* @Description : TODO 自定義線程 - 繼承Thread類
* @Author : lin_refuel@qq.com
*/
public class MyThread extends Thread {
@Override
// 當(dāng)線程被啟動(dòng)時(shí),會(huì)自動(dòng)調(diào)用run方法
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("i = " + i);
}
}
}
創(chuàng)建測(cè)試類demo01
package com.itxs.demo01;
/**
* @Classname : demo01
* @Description : TODO
* @Author : lin_refuel@qq.com
*/
public class demo01 {
public static void main(String[] args) {
// 創(chuàng)建線程對(duì)象
MyThread mt01 = new MyThread();
MyThread mt02 = new MyThread();
MyThread mt03 = new MyThread();
// 通過start方法來啟動(dòng)多線程
mt01.start();
mt02.start();
mt03.start();
}
}
運(yùn)行結(jié)果:每個(gè)線程里面都是執(zhí)行三次循環(huán),并沒有順序,而是誰搶到誰執(zhí)行,
設(shè)置線程名字的兩個(gè)方式
- 調(diào)用方法setName()來設(shè)置線程名字
- 通過構(gòu)造方法來設(shè)置線程名字
demo:
自定義的線程類
package com.itxs.demo01;
/**
* @Classname : MyThread
* @Description : TODO 自定義線程 - 繼承Thread類
* @Author : lin_refuel@qq.com
*/
public class MyThread extends Thread {
// 無參構(gòu)造
public MyThread() {
super();
}
/**
* 帶參數(shù)構(gòu)造,設(shè)置每個(gè)線程名字
* @param name 名字
*/
public MyThread(String name) {
super(name);
}
@Override
// 當(dāng)線程被啟動(dòng)時(shí),會(huì)自動(dòng)調(diào)用run方法
public void run() {
for (int i = 0; i < 3; i++) {
// this當(dāng)前類,getName表示獲取當(dāng)前類的名字
System.out.println(this.getName() + " i = " + i);
}
}
}
測(cè)試類demo01
package com.itxs.demo01;
/**
* @Classname : demo01
* @Description : TODO
* @Author : lin_refuel@qq.com
*/
public class demo01 {
public static void main(String[] args) {
// 創(chuàng)建線程對(duì)象
MyThread mt01 = new MyThread("線程01");
MyThread mt02 = new MyThread("線程02");
MyThread mt03 = new MyThread();
// 設(shè)置每個(gè)線程的名字的方法setName();
// mt01.setName("線程01");
// mt02.setName("線程02");
mt03.setName("線程03");
// 通過start方法來啟動(dòng)多線程
mt01.start();
mt02.start();
mt03.start();
}
}
運(yùn)行結(jié)果:
獲取正在運(yùn)行的線程
調(diào)用下面Thread類中方法,可以獲取當(dāng)前正在運(yùn)行對(duì)象
Thread.currentThread()
main也是一個(gè)線程,設(shè)置main線程名字,沒有辦法通過this.getName和this.setName進(jìn)行設(shè)置,只能通過上面的Thread類中方法進(jìn)行設(shè)置獲取
demo:
注意run方法中,輸出每個(gè)線程名字的地方調(diào)用了Thread.currentThread()
package com.itxs.demo01;
/**
* @Classname : MyThread
* @Description : TODO 自定義線程 - 繼承Thread類
* @Author : lin_refuel@qq.com
*/
public class MyThread extends Thread {
// 無參構(gòu)造
public MyThread() {
super();
}
/**
* 帶參數(shù)構(gòu)造,設(shè)置每個(gè)線程名字
* @param name 名字
*/
public MyThread(String name) {
super(name);
}
@Override
// 當(dāng)線程被啟動(dòng)時(shí),會(huì)自動(dòng)調(diào)用run方法
public void run() {
for (int i = 0; i < 3; i++) {
// this當(dāng)前類,getName表示獲取當(dāng)前類的名字
// System.out.println(this.getName() + " i = " + i);
System.out.println(Thread.currentThread().getName() + " i = " + i);
}
}
}
測(cè)試類demo01: 注意main線程獲取的
package com.itxs.demo01;
/**
* @Classname : demo01
* @Description : TODO
* @Author : lin_refuel@qq.com
*/
public class demo01 {
public static void main(String[] args) {
// 創(chuàng)建線程對(duì)象
MyThread mt01 = new MyThread("線程01");
MyThread mt02 = new MyThread("線程02");
MyThread mt03 = new MyThread();
// 設(shè)置每個(gè)線程的名字的方法setName();
// mt01.setName("線程01");
// mt02.setName("線程02");
mt03.setName("線程03");
// 通過start方法來啟動(dòng)多線程
mt01.start();
mt02.start();
mt03.start();
// 獲取正在運(yùn)行的線程對(duì)象
Thread.currentThread().setName("主線程");// 設(shè)置main線程名字
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "i = " + i);
}
}
}
運(yùn)行結(jié)果:
線程調(diào)度模型和線程優(yōu)先級(jí)設(shè)置
兩種調(diào)度模型
-
兩種線程調(diào)度模型
-
分時(shí)調(diào)度模型:所有線程輪流使用 CPU 的使用權(quán),平均分配每個(gè)線程占用 CPU 的時(shí)間
-
搶占調(diào)度模型:優(yōu)先讓優(yōu)先級(jí)高的線程使用 CPU,如果線程的歐優(yōu)先級(jí)相同,那么隨機(jī)選擇一個(gè),優(yōu)先級(jí)高的線程獲取的 CPU 占用時(shí)間會(huì)相對(duì)多一些
Java 使用的是搶占式的調(diào)度模型
-
優(yōu)先級(jí)設(shè)置
Thread 類中設(shè)置和獲取線程優(yōu)先級(jí)的方法
getPriority()//返回次線程的優(yōu)先級(jí)
setProiority()//更改次線程的優(yōu)先級(jí)
demo:
創(chuàng)建一個(gè)名字為MyThread類繼承Thread類
package com.itxs.demo01;
/**
* @Classname : MyThread
* @Description : TODO 自定義線程 - 繼承Thread類
* @Author : lin_refuel@qq.com
*/
public class MyThread extends Thread {
// 無參構(gòu)造
public MyThread() {
super();
}
/**
* 帶參數(shù)構(gòu)造,設(shè)置每個(gè)線程名字
* @param name 名字
*/
public MyThread(String name) {
super(name);
}
@Override
// 當(dāng)線程被啟動(dòng)時(shí),會(huì)自動(dòng)調(diào)用run方法
public void run() {
for (int i = 0; i < 50; i++) {
// this當(dāng)前類,getName表示獲取當(dāng)前類的名字
// System.out.println(this.getName() + " i = " + i);
System.out.println(Thread.currentThread().getName() + " i = " + i);
}
}
}
測(cè)試類demo02 - 查看優(yōu)先級(jí)高的線程是否能更快執(zhí)行完
package com.itxs.demo01;
/**
* @Classname : demo02
* @Description : TODO 線程優(yōu)先級(jí)測(cè)試運(yùn)行結(jié)果
* @Author : lin_refuel@qq.com
*/
public class demo02 {
public static void main(String[] args) {
// 創(chuàng)建線程
MyThread mt01 = new MyThread("線程01");
MyThread mt02 = new MyThread("線程02");
MyThread mt03 = new MyThread("線程03");
// 設(shè)置每個(gè)線程優(yōu)先級(jí)
mt01.setPriority(Thread.MIN_PRIORITY);// 優(yōu)先級(jí)低
mt02.setPriority(Thread.NORM_PRIORITY);// 優(yōu)先級(jí)不變
mt03.setPriority(Thread.MAX_PRIORITY); // 優(yōu)先級(jí)最高
// 輸出每個(gè)線程優(yōu)先級(jí)
// System.out.println(mt01.getPriority());//1
// System.out.println(mt02.getPriority());//5
// System.out.println(mt03.getPriority());//10
// 開啟線程
mt01.start();
mt02.start();
mt03.start();
}
}
運(yùn)行結(jié)果: 線程mt03比其他兩個(gè)線程運(yùn)行快一點(diǎn),僅僅一點(diǎn)
線程控制
sleep
sleep:使當(dāng)前正在執(zhí)行的線程停留指定的毫秒數(shù)
demo:案例:華山論劍
定義一個(gè)MyThread類繼承Thread類
package com.itxs.demo02;
/**
* @Classname : MyThread
* @Description : TODO
* @Author : lin_refuel@qq.com
*/
public class MyThread extends Thread {
public MyThread() {
super();
}
// 初始化線程名字的構(gòu)造方法
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 1; i <= 20; i++) {
System.out.println(Thread.currentThread().getName() + "打出了第" + i + "招");
// 調(diào)用sleep使其線程執(zhí)行一次循環(huán)后停留1秒
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
sleeptest測(cè)試類
package com.itxs.demo02;
/**
* @Classname : sleepTest
* @Description : TODO sleep測(cè)試類
* @Author : lin_refuel@qq.com
*/
public class sleepTest {
public static void main(String[] args) {
// 創(chuàng)建線程對(duì)象
MyThread mt01 = new MyThread("黃固");
MyThread mt02 = new MyThread("歐陽(yáng)鋒");
MyThread mt03 = new MyThread("段智興");
MyThread mt04 = new MyThread("洪七公");
// 開啟線程
mt01.start();
mt02.start();
mt03.start();
mt04.start();
}
}
join
join:等待線程結(jié)束
package com.itxs.demo03;
/**
* @Classname : MyThread
* @Description : TODO 自定義線程類 - 繼承Thread類
* @Author : lin_refuel@qq.com
*/
public class MyThread extends Thread {
public MyThread() {
super();
}
// 設(shè)置線程名字
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"報(bào)數(shù):"+i);
}
}
}
test:測(cè)試類,注意join的使用,需要拋出異常
package com.itxs.demo03;
/**
* @Classname : test
* @Description : TODO
* @Author : lin_refuel@qq.com
*/
public class test {
public static void main(String[] args) throws InterruptedException {
// 三個(gè)人報(bào)數(shù),第一個(gè)人報(bào)完數(shù)后,其他人才能報(bào)數(shù)
MyThread mt01 = new MyThread("1號(hào)");
MyThread mt02 = new MyThread("2號(hào)");
MyThread mt03 = new MyThread("3號(hào)");
// 開始報(bào)數(shù)
mt01.start();
mt01.join();//等待第一個(gè)人報(bào)數(shù)完畢
mt02.start();
mt03.start();
}
}
守護(hù)線程
setDaemon(boolean on)
將此線程標(biāo)記為守護(hù)進(jìn)程,當(dāng)運(yùn)行線程都是守護(hù)線程時(shí),JVM 將退出
個(gè)人理解:主線程里面運(yùn)行結(jié)束,守護(hù)線程不會(huì)繼續(xù)執(zhí)行
例子:老板帶三個(gè)員工吃飯,老板吃飽后,員工不能繼續(xù)吃了
demo:
定義MyThread類繼承Thread類
package com.itxs.demo04;
/**
* @Classname : MyThread
* @Description : TODO
* @Author : lin_refuel@qq.com
*/
public class MyThread extends Thread {
public MyThread() {
super();
}
// 設(shè)置線程對(duì)象名字
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 1; i <= 50; i++) {
System.out.println(Thread.currentThread().getName() + "正在吃" + i + "口");
}
}
}
定義三個(gè)線程設(shè)置為守護(hù)線程,進(jìn)行測(cè)試,注意守護(hù)線程設(shè)置方式
package com.itxs.demo04;
/**
* @Classname : test
* @Description : TODO
* @Author : lin_refuel@qq.com
*/
public class test {
public static void main(String[] args) {
// 創(chuàng)建三個(gè)工人線程
MyThread mt01 = new MyThread("1號(hào)工人");
MyThread mt02 = new MyThread("1號(hào)工人");
MyThread mt03 = new MyThread("1號(hào)工人");
System.out.println("吃飯了");
// 三個(gè)工人線程設(shè)置為守護(hù)線程,老板說吃飽了,工人就不繼續(xù)吃了
mt01.setDaemon(true);
mt02.setDaemon(true);
mt03.setDaemon(true);
mt01.start();
mt02.start();
mt03.start();
// 主線程:作為老板
Thread.currentThread().setName("老板");
for (int i = 1; i <5; i++) {
System.out.println(Thread.currentThread().getName() + "正在吃第" + i + "口");
}
System.out.println("老板說吃飽了,咱們走吧");
}
}
線程生命周期
-
新建:創(chuàng)建線程對(duì)象(通過
start()
進(jìn)入下一個(gè)環(huán)節(jié)) -
就緒:有執(zhí)行資格,沒有執(zhí)行權(quán)(搶占 CPU 的執(zhí)行權(quán))
-
運(yùn)行:有執(zhí)行資格,有執(zhí)行權(quán)(可能被其他線程搶走 CPU 的執(zhí)行權(quán),則回到就緒狀態(tài),若遇到阻塞式方法,則失去運(yùn)行權(quán)和執(zhí)行這個(gè),等待,當(dāng)阻塞方法調(diào)用結(jié)束之后,回到就緒狀態(tài))文章來源:http://www.zghlxwxcb.cn/news/detail-796423.html
-
死亡:線程死亡,成為垃圾文章來源地址http://www.zghlxwxcb.cn/news/detail-796423.html
到了這里,關(guān)于java中多線程的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!