7、多線(xiàn)程(1)

一、基本概念

  • 1.程序:指令集 靜態(tài)概念

  • 2.進(jìn)程:操作系統(tǒng)調(diào)度程序,是一個(gè)動(dòng)態(tài)的概念。是程序的一次動(dòng)態(tài)執(zhí)行的過(guò)程,占用特定的地址空間。每個(gè)進(jìn)程都是獨(dú)立的,由3部分組成cpu、data、code。缺點(diǎn):內(nèi)存的浪費(fèi),cpu負(fù)擔(dān)重。

  • 3.線(xiàn)程:在進(jìn)程內(nèi)多條執(zhí)行路徑。線(xiàn)程是進(jìn)程中一個(gè)單一的連續(xù)控制流程(執(zhí)行路徑)。線(xiàn)程又被稱(chēng)為輕量級(jí)進(jìn)程,一個(gè)進(jìn)程可擁有多個(gè)并行的線(xiàn)程,一個(gè)進(jìn)程中的線(xiàn)程共享相同的內(nèi)存單元/內(nèi)存地址空間-->可以訪問(wèn)相同的變量和對(duì)象,而且它們從同一堆中分配對(duì)象-->通信、數(shù)據(jù)交換、同步操作。由于線(xiàn)程間的通信是在同一地址空間上進(jìn)行的,所以不需要額外的通信機(jī)制,這就使得通信更簡(jiǎn)便而且信息傳遞的速度也更快。

  • 4.比較

區(qū)別 進(jìn)程 線(xiàn)程
根本區(qū)別 作為資源分配的單位 調(diào)度和執(zhí)行的單位
開(kāi)銷(xiāo) 每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間(進(jìn)程上下文),進(jìn)程間的切換會(huì)有較大的開(kāi)銷(xiāo) 線(xiàn)程可以看成是輕量級(jí)的進(jìn)程,同一類(lèi)線(xiàn)程共享代碼和數(shù)據(jù)空間,每個(gè)線(xiàn)程有獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器PC線(xiàn)程切換的開(kāi)銷(xiāo)小
所處環(huán)境 在操作系統(tǒng)中能同時(shí)運(yùn)行多個(gè)任務(wù)(程序) 在同一應(yīng)用程序中有多個(gè)順序流同時(shí)執(zhí)行
分配內(nèi)存 系統(tǒng)在運(yùn)行的時(shí)候會(huì)為每個(gè)進(jìn)程分配不同的內(nèi)存區(qū)域 除了cpu之外,不會(huì)為線(xiàn)程分配內(nèi)存(線(xiàn)程所使用的資源是它所屬的進(jìn)程的資源)線(xiàn)程組只能共享資源
包含關(guān)系 沒(méi)有線(xiàn)程的進(jìn)程是可以被看作單線(xiàn)程的,如果一個(gè)進(jìn)程內(nèi)擁有多個(gè)線(xiàn)程,則執(zhí)行過(guò)程不是一條線(xiàn)程的,而是多條線(xiàn)(線(xiàn)程)共同完成的 線(xiàn)程是進(jìn)程的一部分,所以線(xiàn)程有的時(shí)候被稱(chēng)為是輕量級(jí)進(jìn)程或輕權(quán)進(jìn)程

二、相關(guān)類(lèi)的使用

2.1 使用Thread類(lèi)實(shí)現(xiàn)多線(xiàn)程

這里我們給出一個(gè)簡(jiǎn)單的例子:
Rabbit_01.java

package cn.itcast.day169.thread;
/*
 * 模擬龜兔賽跑
 * 1、創(chuàng)建多線(xiàn)程,繼承Thread類(lèi)+重寫(xiě)run方法(其中的代碼都是線(xiàn)程體)
 * 2、使用線(xiàn)程:創(chuàng)建子類(lèi)對(duì)象+對(duì)象.start(),調(diào)用start方法表示線(xiàn)程的啟動(dòng)
 * */
//兔子
public class Rabbit_01 extends Thread{
    public void run() {
        //線(xiàn)程體
        for(int i = 0; i < 100; i++){
            System.out.println("兔子跑了: " + i + "步");
        }
    }
}
//烏龜
class Tortoise extends Thread{
    public void run() {
        //線(xiàn)程體
        for(int i = 0; i < 100; i++){
            System.out.println("烏龜跑了: " + i + "步");
        }
    }
}

RabbitApp_01.java

package cn.itcast.day169.thread;
//我們會(huì)將此類(lèi)加到一個(gè)線(xiàn)程組中
public class RabbitApp_01 {
    public static void main(String[] args) {
        //創(chuàng)建子類(lèi)對(duì)象
        Rabbit_01 rab = new Rabbit_01();
        Tortoise tor = new Tortoise();
        //調(diào)用start方法
        rab.start();//不要調(diào)用run方法,調(diào)用run方法只是調(diào)用一個(gè)普通方法,沒(méi)有開(kāi)啟一個(gè)線(xiàn)程
        tor.start();//此時(shí)這里就有兩條線(xiàn)程了
        for(int i = 0; i < 1000; i++){
            System.out.println("main " + i );
        }
    }
}

說(shuō)明:這里可以看到我們通過(guò)繼承Thread類(lèi)實(shí)現(xiàn)了多線(xiàn)程,但是很明顯有個(gè)缺點(diǎn),就是如果一個(gè)類(lèi)本身就已經(jīng)繼承了一個(gè)父類(lèi),那么此類(lèi)就不能再繼承Thread類(lèi)來(lái)實(shí)現(xiàn)多線(xiàn)程了。

2.2 使用Runnable實(shí)現(xiàn)多線(xiàn)程

為了解決上面的問(wèn)題,我們可以實(shí)現(xiàn)Runnable接口。優(yōu)點(diǎn):可以同時(shí)實(shí)現(xiàn)繼承,實(shí)現(xiàn)Runnable接口方式要通用一些。

  • 1)避免單繼承
  • 2)方便共享資源 , 同一份資源, 多個(gè)代理訪問(wèn)。

Runnable使用了靜態(tài)代理的設(shè)計(jì)模(繼承相同的接口),首先我們看什么是靜態(tài)設(shè)計(jì)模式:
StaticProxy.java

package cn.itcast.day169.thread;
/*靜態(tài)代理
 * 1、真實(shí)角色
 * 2、代理角色:要持有真實(shí)角色的引用
 * 3、二者實(shí)現(xiàn)相同的接口
 * */
public class StaticProxy {
    public static void main(String[] args) {
        You you = new You();//創(chuàng)建真實(shí)角色
        //創(chuàng)建代理角色+ 持有真實(shí)角色的引用
        WeddingCompany company = new WeddingCompany(you);
        //執(zhí)行任務(wù)
        company.marry();
    }
}

//接口
interface Marry{
    public abstract void marry();
}

//真實(shí)角色
class You implements Marry{
    public void marry() {
        System.out.println("you and girlfriend marry");
    }
}

//代理角色
class WeddingCompany implements Marry{
    private Marry you ;
    public WeddingCompany() {}
    //這里我們通過(guò)構(gòu)造方法傳遞真實(shí)引用,當(dāng)然我們也可以使用setter方法來(lái)傳遞
    public WeddingCompany(Marry you) {
        this.you = you;
    }
    
    private void befor(){
        System.out.println("布置新房");
    }

    public void marry() {
        //在這里我們可以添加一些真實(shí)對(duì)象中沒(méi)有的方法,完成一些額外的工作
        befor();
        you.marry();
        after();
    }
    private void after(){
        System.out.println("鬧婚房");
    }
}

說(shuō)明:靜態(tài)代理本質(zhì)上就是一個(gè)類(lèi)替代執(zhí)行另一個(gè)類(lèi)的相關(guān)方法,在執(zhí)行此方法的時(shí)候還會(huì)附加執(zhí)行一些操作,而不是直接去執(zhí)行實(shí)際類(lèi)的方法,相當(dāng)于一種擴(kuò)展。在實(shí)現(xiàn)靜態(tài)代理的時(shí)候需要注意的是,代理類(lèi)和被代理類(lèi)需要實(shí)現(xiàn)相同的接口,而執(zhí)行的方法都是代理類(lèi)中的方法,同時(shí)代理類(lèi)中的方法需要完成被代理類(lèi)中需要完成的功能。例子中代理類(lèi)WeddingCompany 和被代理類(lèi)You 都繼承的接口是Marry,本來(lái)是You結(jié)婚,但是我們將這項(xiàng)工作交給代理類(lèi),不僅完成結(jié)婚的工作,還處理了一些其他事情。

下面我們看如何使用Runnable實(shí)現(xiàn)多線(xiàn)程:
Programer.java

package cn.itcast.day169.thread;
//使用Runnable創(chuàng)建線(xiàn)程
/*1、類(lèi)實(shí)現(xiàn)Runable接口,重寫(xiě)run方法-->真實(shí)角色類(lèi)
 * */
public class Programer implements Runnable{
    public void run() {
        for(int i = 0; i < 1000; i++){
            System.out.println("一邊做a, 一邊做b");
        }
    }
}

ProgramerApp.java

package cn.itcast.day169.thread;
//使用Runnable創(chuàng)建線(xiàn)程
/*1、類(lèi)實(shí)現(xiàn)Runable接口,重寫(xiě)run方法-->真實(shí)角色類(lèi)
* 2.啟動(dòng)多線(xiàn)程,使用靜態(tài)代理
*   1)創(chuàng)建真實(shí)角色
*   2)創(chuàng)建代理角色
*   3)調(diào)用start方法啟動(dòng)線(xiàn)程 
* */
public class ProgramerApp {
    public static void main(String[] args) {
        //1)創(chuàng)建真實(shí)角色
        Programer programer = new Programer();
        //2)創(chuàng)建代理角色
        Thread proxy = new Thread(programer);
        //3)調(diào)用start方法啟動(dòng)線(xiàn)程 
        proxy.start();
        for(int i = 0; i < 1000; i++){
            System.out.println("一邊聊天");
        }
    }
}

說(shuō)明:這里我們看到實(shí)現(xiàn)實(shí)例化被代理類(lèi)Programer ,然后使用此類(lèi)創(chuàng)建Thread代理類(lèi)。這樣便實(shí)現(xiàn)了多線(xiàn)程。這里我們推薦使用這種方法。此種方式避免單繼承的局限性,同時(shí)方便共享資源。

2.3 通過(guò)Callable接口實(shí)現(xiàn)多線(xiàn)程

  • 在上面的方式中我們可以看到使用Runnable接口時(shí),run方法是不能有返回值的,但是有時(shí)候我們不可避免的希望得到返回值,此時(shí)我們就可以使用Callable這個(gè)接口。Callable是類(lèi)似于Runnable的接口,實(shí)現(xiàn)Callable接口的類(lèi)和實(shí)現(xiàn)Runnable的類(lèi)都是可被其它線(xiàn)程執(zhí)行的任務(wù)。

  • CallableRunnable有幾點(diǎn)不同:
    1)Callable規(guī)定的方法是call(),而Runnable規(guī)定的方法是run
    2)call方法可拋出異常,而run方法是不能拋出異常的
    3)Callable的任務(wù)執(zhí)行后返回值,運(yùn)行Callable任務(wù)可拿到一個(gè)Future對(duì)象,而Runnable的任務(wù)是不能返回值的。Futrue表示異步計(jì)算的結(jié)果。它提供了檢查計(jì)算是否完成的方法啊,以等待計(jì)算的完成,并檢索計(jì)算的結(jié)果。通過(guò)Future對(duì)象可以了解任務(wù)執(zhí)行的情況,可取任務(wù)的執(zhí)行,還可以獲取任務(wù)的執(zhí)行的結(jié)果。
    缺點(diǎn):繁瑣

  • 使用方式
    1)創(chuàng)建Callable實(shí)現(xiàn)類(lèi)+重寫(xiě)call方法
    2)借助執(zhí)行調(diào)度服務(wù)ExecutorService獲取Futrue對(duì)象

ExecutorService ser = Executors.newFixedThreadPool(2);
Futrure result = ser.submit(實(shí)現(xiàn)類(lèi)對(duì)象);

3)、獲取值result.get()
4)停止服務(wù)ser.shutdownNow()

Callable_01.java

package cn.itcast.day169.thread;
import java.util.concurrent.*;
/*使用Callable創(chuàng)建線(xiàn)程 */
public class Callable_01 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //創(chuàng)建兩個(gè)線(xiàn)程
        ExecutorService service = Executors.newFixedThreadPool(2);
        Race tortoise = new Race("千年王八", 1000);
        Race rabbit = new Race("兔子", 500);
        //獲取值
        Future<Integer> result1 = service.submit(tortoise);
        Future<Integer> result2 = service.submit(rabbit);
        Thread.sleep(2000);//2秒
        tortoise.setFlag(false);//停止線(xiàn)程體循環(huán)
        rabbit.setFlag(false);
        int num1 = result1.get();
        int num2 = result2.get();
        System.out.println("烏龜跑了 " + num1 + "步");
        System.out.println("兔子跑了 " + num2 + "步");
        //關(guān)閉線(xiàn)程
        service.shutdownNow();
    }
}

class Race implements Callable<Integer>{
    private String name ;//名稱(chēng)
    private long time ;//延時(shí)時(shí)間,用來(lái)表示速度
    private boolean flag = true;
    private int step = 0;//步
    
    public Race(){}
    public Race(String name ){
        this.name = name;
    }

    public Race(String name, long time) {
        this.name = name;
        this.time = time;
    }
    //重寫(xiě)call方法
    public Integer call() throws Exception {
        while(flag){
            Thread.sleep(time);
            step++;
        }
        return step;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public long getTime() {
        return time;
    }
    public void setTime(long time) {
        this.time = time;
    }
    public boolean isFlag() {
        return flag;
    }
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
    public int getStep() {
        return step;
    }
    public void setStep(int step) {
        this.step = step;
    }
}

說(shuō)明:這里的使用方式和之前的稍微有點(diǎn)不同。

三、線(xiàn)程狀態(tài)

3.1 基本概念

  • 線(xiàn)程被創(chuàng)建之后我們調(diào)用start方法,此時(shí)線(xiàn)程進(jìn)入就緒狀態(tài)(可運(yùn)行狀態(tài)),當(dāng)cpu調(diào)度的時(shí)候進(jìn)入運(yùn)行狀態(tài),當(dāng)線(xiàn)程執(zhí)行完后此線(xiàn)程就停止了,即終止?fàn)顟B(tài)。但是如果線(xiàn)程在還沒(méi)有執(zhí)行完的時(shí)候被停止,那么就進(jìn)入阻塞狀態(tài),如果阻塞狀態(tài)解除之后線(xiàn)程又進(jìn)入就緒狀態(tài),在之后cpu調(diào)度則還會(huì)接著進(jìn)入運(yùn)行狀態(tài)進(jìn)行執(zhí)行。

  • 這里注意:死亡狀態(tài)是線(xiàn)程聲明周期中的最后一個(gè)階段,線(xiàn)程死亡的原因有兩個(gè)。一個(gè)是正常執(zhí)行完,一個(gè)是線(xiàn)程被強(qiáng)制性的終止工作,如果通過(guò)執(zhí)行stopdestroy方法來(lái)終止一個(gè)線(xiàn)程(不推薦使用這兩個(gè)方法),前者會(huì)產(chǎn)生異常,后者是強(qiáng)制終止,不會(huì)釋放鎖。

  • 死亡狀態(tài)如何停止線(xiàn)程
    在之前的例子中,其實(shí)我們已經(jīng)看到,我們可以通過(guò)一個(gè)標(biāo)志來(lái)停止線(xiàn)程。
    1、自然終止
    2、外部干涉

    • 1)線(xiàn)程類(lèi)中定義線(xiàn)程體使用的標(biāo)志
    • 2)線(xiàn)程體使用該標(biāo)志
    • 3)提供對(duì)外的方法可以改變?cè)摌?biāo)志
    • 4)外部根據(jù)條件調(diào)用該方法即可

使用標(biāo)志位來(lái)停止線(xiàn)程:

package cn.itcast.day174.thread01;
public class Demo01 {
    public static void main(String[] args) {
        Study s = new Study();
        new Thread(s).start();
        //外部干涉
        for(int i = 0; i < 100; i++){
            if(i == 50){//注意:這里停下來(lái)的時(shí)間點(diǎn)不是很準(zhǔn)確,由cpu決定
                s.stop();
            }
            System.out.println("main-->" + i);
        }
    }
}

class Study implements Runnable{
    private boolean flag = true;
    public void run() {
        while(flag){
            System.out.println("study thread...");
        }
    }
    //對(duì)外提供該表標(biāo)志的方法
    public void stop(){
        this.flag = false;
    }
}
  • 阻塞
    • 1、join:合并線(xiàn)程,將多條線(xiàn)程合并為一個(gè)
    • 2、yield:暫停當(dāng)前線(xiàn)程(暫停自己),執(zhí)行其他線(xiàn)程
    • 3、sleep:暫停線(xiàn)程,休眠的時(shí)候不會(huì)釋放鎖。相關(guān)應(yīng)用:
      1)與時(shí)間相關(guān):數(shù)數(shù)和倒計(jì)時(shí)
      2)模擬網(wǎng)絡(luò)延時(shí)

合并線(xiàn)程

package cn.itcast.day174.thread01;
/*合并線(xiàn)程 */
public class JoinDemo01 extends Thread{
    
    public static void main(String[] args) throws InterruptedException {
        
        JoinDemo01 demo = new JoinDemo01();
        Thread t = new Thread(demo);//新生狀態(tài)
        t.start();//就緒狀態(tài)
        //cpu調(diào)度就進(jìn)入運(yùn)行狀態(tài)
        
        for(int i = 0; i < 100; i++){
            if(i == 50){
                //此時(shí)main方法阻塞了,必須讓線(xiàn)程t運(yùn)行完,就是剛開(kāi)始誰(shuí)先執(zhí)行都是隨機(jī)的,
                //但是當(dāng)i的值為50后,便是t線(xiàn)程執(zhí)行完后main線(xiàn)程才能再次執(zhí)行
                t.join();
            }
            System.out.println("main..." + i);
        }
    }
    
    public void run(){
        for(int i = 0; i < 100; i++){
            System.out.println("join..." + i);
        }
    }
}

說(shuō)明:這里其實(shí)是有兩個(gè)線(xiàn)程,一個(gè)是線(xiàn)程t,一個(gè)是main。開(kāi)始時(shí)是并發(fā)執(zhí)行,但是到i的值為50的時(shí)候便需要t線(xiàn)程運(yùn)行完成之后main線(xiàn)程才能開(kāi)始執(zhí)行。

暫停當(dāng)前線(xiàn)程

package cn.itcast.day174.thread01;
/*暫停執(zhí)行當(dāng)前的線(xiàn)程(暫停自己),并執(zhí)行其他線(xiàn)程*/
public class YieldDemo01 extends Thread{
    public static void main(String[] args) throws InterruptedException {
        
        YieldDemo01 demo = new YieldDemo01();
        Thread t = new Thread(demo);//新生狀態(tài)
        t.start();//就緒狀態(tài)
        //cpu調(diào)度就進(jìn)入運(yùn)行狀態(tài)
        
        for(int i = 0; i < 100; i++){
            if(i % 20 == 0){
                //注意:這里的暫停不是很?chē)?yán)格
                Thread.yield();//暫停自己,注意:寫(xiě)在誰(shuí)的線(xiàn)程體內(nèi)就暫停誰(shuí)(這里暫停main),效果不是很明顯
            }
            System.out.println("main..." + i);
        }
    }
    
    public void run(){
        for(int i = 0; i < 100; i++){
            System.out.println("yield..." + i);
        }
    }
}

說(shuō)明:這里一定要注意到底是暫停哪個(gè)線(xiàn)程。

數(shù)數(shù)和倒計(jì)時(shí)

package cn.itcast.day174.thread01;
import java.util.Date;
import java.text.SimpleDateFormat;

//倒計(jì)時(shí),倒數(shù)十個(gè)數(shù),一秒內(nèi)打印一個(gè)
public class SleepDemo01 {
    public static void main(String[] args) throws InterruptedException {
        test2();
    }

    public static void test1() throws InterruptedException {
        int num = 10;
        while (true) {
            System.out.println(num--);
            Thread.sleep(1000);// 暫停
            if (num <= 0) {
                break;
            }
        }
    }

    // 倒計(jì)時(shí)
    public static void test2() throws InterruptedException {
        Date endTime = new Date(System.currentTimeMillis() + 10 * 1000);
        long end = endTime.getTime();
        while (true) {
            System.out.println(new SimpleDateFormat("mm:ss").format(endTime));
            endTime = new Date(endTime.getTime() - 1000);
            Thread.sleep(1000);
            if (end - 10000 > endTime.getTime()) {
                break;
            }
        }
    }
}

模擬網(wǎng)絡(luò)延時(shí)

package cn.itcast.day174.thread01;
//模擬網(wǎng)絡(luò)延時(shí),可能出現(xiàn)并發(fā)問(wèn)題
public class SleepDemo02 {
    public static void main(String[] args) {
        Web12306 web = new Web12306();//真實(shí)角色
        //代理對(duì)象
        Thread t1 = new Thread(web, "黃牛1");//第二個(gè)參數(shù)是當(dāng)前線(xiàn)程的名字
        Thread t2 = new Thread(web, "黃牛2");
        Thread t3 = new Thread(web, "黃牛3");
        //啟動(dòng)線(xiàn)程
        t1.start();
        t2.start();
        t3.start();
    }
}

class Web12306 implements Runnable{
    private int num = 50;
    public void run() {
        while(true){
            if(num <= 0){
                break;
            }
            try {
                Thread.sleep(500);//500ms的延時(shí)
                //加入延時(shí)之后可能會(huì)造成資源沖突的問(wèn)題,這就是并發(fā)問(wèn)題
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "搶到了第" + num-- + "張票");
        }
    }
}
  • 線(xiàn)程基本信息
方法 功能
isAlive() 判斷線(xiàn)程是否還“活”著,即線(xiàn)程是否還未終止
getPriority() 獲得線(xiàn)程的優(yōu)先級(jí)數(shù)值
setPriority() 設(shè)置線(xiàn)程的優(yōu)先級(jí)數(shù)值
setName() 給線(xiàn)程一個(gè)名字
getName() 取得線(xiàn)程的名字
currentThread() 取得當(dāng)前正在運(yùn)行的線(xiàn)程對(duì)象,也就是取得自己本身

下面給出兩個(gè)例子:
MyThread.java

package cn.itcast.day174.thread01;
public class MyThread implements Runnable {
    private boolean flag = true;
    private int num = 0;

    public void run() {
        while (flag) {
            System.out.println(Thread.currentThread().getName() + num++);
        }
    }

    public void stop() {
        this.flag = false;
    }
}

InfoDemo01.java

package cn.itcast.day174.thread01;
//currentThread()靜態(tài)方法
public class InfoDemo01 {
    public static void main(String[] args) throws InterruptedException {
        MyThread t1 = new MyThread();
        Thread proxy = new Thread(t1, "t1線(xiàn)程");//第二個(gè)參數(shù)是線(xiàn)程的名稱(chēng)
        //我們也可以這樣設(shè)置線(xiàn)程名稱(chēng)
        proxy.setName("狗蛋");
        System.out.println(proxy.getName());
        System.out.println(Thread.currentThread().getName());//獲取名稱(chēng)
        proxy.start();
        System.out.println("線(xiàn)程啟動(dòng)后的狀態(tài): " + proxy.isAlive());//查看線(xiàn)程是否“活著”
        Thread.sleep(200);
        t1.stop();
        Thread.sleep(200);
        System.out.println("線(xiàn)程停止后的狀態(tài): " + proxy.isAlive());
    }
}

InfoDemo02.java

package cn.itcast.day174.thread01;
//優(yōu)先級(jí)
//MAX_PRIORITY  10最大
//MIN_PRIORITY  1最小
//NORM_PRIORITY  5默認(rèn)
//優(yōu)先級(jí)不代表絕對(duì)的優(yōu)先,沒(méi)有先后順序,代表的是概率
public class InfoDemo02 {
    public static void main(String[] args) throws InterruptedException {
        MyThread t1 = new MyThread();
        Thread p1 = new Thread(t1, "t1線(xiàn)程");
        MyThread t2 = new MyThread();
        Thread p2 = new Thread(t2, "t2線(xiàn)程");
        p1.setPriority(Thread.MIN_PRIORITY);//設(shè)置優(yōu)先級(jí)
        p2.setPriority(Thread.MAX_PRIORITY);//設(shè)置優(yōu)先級(jí)
        p1.start();
        p2.start();
        
        Thread.sleep(100);
        t1.stop();
        t2.stop();
    }
}

說(shuō)明:這兩個(gè)例子都是用來(lái)取得線(xiàn)程的一些信息。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,933評(píng)論 18 139
  • 下面是我自己收集整理的Java線(xiàn)程相關(guān)的面試題,可以用它來(lái)好好準(zhǔn)備面試。 參考文檔:-《Java核心技術(shù) 卷一》-...
    阿呆變Geek閱讀 14,905評(píng)論 14 507
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線(xiàn)程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,765評(píng)論 18 399
  • 新的一年,新的開(kāi)始,新的計(jì)劃,新的目標(biāo),新的跨越,心懷感恩!
    德菲閱讀 208評(píng)論 3 1
  • 這兩天小編朋友圈的畫(huà)風(fēng)頗為清奇,刷了下微博才知道原來(lái)是鹿晗有女朋友了,還是“國(guó)民閨女”關(guān)曉彤。對(duì)于吃瓜群眾的小編我...
    趣讀書(shū)吧閱讀 234評(píng)論 0 0