Java多线程编程(二)——线程的常见方法

使用getName()获取线程的名字

Thread类中设置线程的名字

1.setName()更改线程的名字

2.通过构造方法更改线程的名字

获取当前线程的对象

线程的休眠

线程的优先级

线程调度

关于优先级的常见方法

守护线程\后台线程


使用getName()获取线程的名字

线程是有默认名字的,格式为 :Thread-编号

我们可以进入Thread类中查看一下源码

选中Thread ,ctrl + B

再使用 Alt + 7,开启骨架

 选择Thread() 的空参构造方法

public Thread() {     
    this((ThreadGroup)null, (Runnable)null, "Thread-" + nextThreadNum(), 0L);
}

getName()方法的使用 

@Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            //Thread时有默认名字的!
            System.out.println(getName() + "@@@" + i);
        }
    }

Thread类中设置线程的名字

1.setName()更改线程的名字

MyThread T1 = new MyThread();
T1.setName("第一条线程");

2.通过构造方法更改线程的名字

初学者常见错误——“直接在MyThread中填入参数”

即:MyThread T1 = new MyThread(“第一条线程”);

错误原因:

我们创建的不是Thread类对象,而是其子类的对象MyThrad,在其子类中我们没有写带参构造方法,虽然他们有继承关系,But构造方法只能被子类使用super关键字去调用。

正确写法:

package 多线程.ThreadDemo04;

//ctrl + B 进入Thread类中查看源码
//Alt + 7 导出项目类的骨架
//Alt + Insert 打开Generate

public class MyThread extends Thread{
    /**
     * 我们创建的不是Thread对象,而是Thread的子类对象MyThread
     * 在其子类MyThread中没有带参构造
     * 构造方法只能被子类用 super 关键字调用!!!
     */
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            //Thread时有默认名字的!
            System.out.println(getName() + "@@@" + i);
        }
    }
}
package 多线程.ThreadDemo04;

//ctrl + B 进入Thread类中查看源码
//Alt + 7 导出项目类的骨架
//Alt + Insert 打开Generate

public class MyThread extends Thread{
    /**
     * 我们创建的不是Thread对象,而是Thread的子类对象MyThread
     * 在其子类MyThread中没有带参构造
     * 构造方法只能被子类用 super 关键字调用!!!
     */
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            //Thread时有默认名字的!
            System.out.println(getName() + "@@@" + i);
        }
    }
}

获取当前线程的对象

public static Thread currentThread() : 返回当前正在执行的线程对象的引用

比如在Runnable中,想要使用getName()方法,不能直接使用getName() 方法,这是因为MyRunnable没有继承Thread

但是我们可以使用Thread.currentThread()先获取当前线程的对象,再调用getName()方法即可。

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "---" + i);
        }
    }
}

线程的休眠

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(3000);
        System.out.println("3秒后打印!");
    }
}

注意此处的异常抛出!

在Runnable中使用sleep()有一个小细节要注意:

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            /**
             * 如果一个类 or 接口中的方法没有抛出异常
             * 那么他的子类 or 实现类 就不可以抛出异常!
             * 只能使用 try-catch
             */
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---" + i);
        }
    }
}

这里异常的抛出是用了try-catch的方式,我们可以ctrl + B 进入Runnable接口中看看

如果一个类 or 接口 他们的方法没有抛出异常,那么他们的子类重写此方法时就不可以抛出异常,只能使用try-catch。

线程的优先级

线程调度

两种调度方式

        分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片

        抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些

Java使用的是抢占式调度模型

随机性

假如计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的

关于线程调度这一块的内容没法详细说,不懂的可以看看王道的视频

关于优先级的常见方法

方法名说明
final int getPriority()返回此线程的优先级  //默认是5
final void setPriority(int newPriority)更改此线程的优先级线程默认优先级是5;线程优先级的范围是:1-10

Coding:

public class Demo {
    public static void main(String[] args) {
        
        //优先级: 1 - 10 默认值:5
        MyCallable mc = new MyCallable();
        FutureTask<String> ft = new FutureTask<>(mc);
        Thread t1 = new Thread(ft);
        t1.setName("火箭");
        
        //不设置默认优先级是 5
        System.out.println(t1.getPriority());
        t1.start();
    
        MyCallable mc2 = new MyCallable();
        FutureTask<String> ft2 = new FutureTask<>(mc2);
        Thread t2 = new Thread(ft2);
        t2.setName("飞机");
        
        //设置优先级为 10 
        t2.setPriority(10);
        t2.start();
    }
}

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "---" + i);
        }
        return "线程执行完毕了";
    }
}

注意:线程的优先级越大,是指线程抢到CPU资源的几率更大,而不是说优先级高的线程必然先执行!

守护线程\后台线程

任何一个守护线程都是整个JVM中所有非守护线程的保姆;
守护线程类似于整个进程的一个默默无闻的小喽啰;它的生死无关重要,它却依赖整个进程而运行;哪天其他线程结束了,没有要执行了,程序就结束了,理都没理守护线程,就把它中断了;

方法名说明
void setDaemon(boolean on)将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出

把将线程设置为守护线程,当普通线程执行完之后,那么守护线程也没有继续运行下去的必要了。

但是不会立马停止,由于CPU运行速度很快,守护线程还是会再“挣扎一会”!然后停止。

在Coding中注意:守护线程不能持有任何需要关闭的资源,例如打开文件等,因为虚拟机退出时,守护线程没有任何机会来关闭文件,这会导致数据丢失。

下一个章节

Java多线程编程(三)——线程锁icon-default.png?t=LBL2https://blog.csdn.net/weixin_43715214/article/details/122340783?spm=1001.2014.3001.5501

posted @   金鳞踏雨  阅读(27)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示