多线程学习三,线程的分类

多线程学习三,线程的分类:主线程、守护线程、子线程

文章目录

  • 多线程学习三,线程的分类:主线程、守护线程、子线程
    • 1. 主线程
    • 2. 精灵线程
    • 3. 线程优先级

思维导图:

多线程学习三,线程的分类_第1张图片

1. 主线程

main线程启动的就是主线程

那么在Java中一个类里只有一个线程吗?不是的,Java天生就是多线程的,即使在一个简单的Hello World程序中也会有很多线程的产生。

多线程学习三,线程的分类_第2张图片

2. 精灵线程

在Java中,线程可以简单分为两种类型:用户线程(User Thread)守护线程(Daemon Thread)。在一个Java程序中,任何一个守护线程都是整个JVM中所有非守护线程的保姆:

只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。

下面我们来举一个用户线程退出,守护线程被迫结束的例子:

这里值得注意的是,需要先开启用户线程再开启子线程

public class _9_daemon {
    public static void main(String[] args) {
        Thread t1=new CommonThread();
        //新建任务、再绑定到一个线程上
        Thread t2 = new Thread(new MyDaemon());
        //将t2设置为守护线程
        t2.setDaemon(true);
        //正确做法,线程运行前设置守护线程
        t2.start();
        t1.start();
    }
}
//自定义线程,继承自Thread
class CommonThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("用户线程第"+i+"此执行");
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//任务类
class MyDaemon implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("用户线程第"+i+"此执行");
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

从运行结果可以看到,当用户线程退出后,守护线程也自动退出了

守护线程第0此执行
用户线程第0此执行
守护线程第1此执行
用户线程第1此执行
用户线程第2此执行
守护线程第2此执行
守护线程第3此执行
用户线程第3此执行
守护线程第4此执行
用户线程第4此执行
守护线程第5此执行

3. 线程优先级

我们可以通过设置线程的优先级来控制线程的执行顺序,但是我们并不能精准控制,到底是谁先运行,这其实是一件概率事件,并不能确定,举个栗子:

public class _10_Priority {
    public static void main(String[] args) {
        ShowTime task = new ShowTime();
        Thread t1 = new Thread(task,"线程一");
        //设置线程的优先级
        t1.setPriority(1);
        t1.start();

        Thread t2 = new Thread(task, "线程二");
        t2.setPriority(10);
        t2.start();
    }
}

class ShowTime implements Runnable{
    @Override
    public void run() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
        while (true){
            System.out.println(Thread.currentThread().getName()+"当前的时间为:"+sdf.format(System.currentTimeMillis()));
            try {
            	Thread.sleep(1000);
            } catch (Exception e) {
            	e.printStackTrace();
            }
        }
    }
}

我们来看一下打印的结果:

线程一当前的时间为:2022年01月27日 02:15:55
线程二当前的时间为:2022年01月27日 02:15:55
线程一当前的时间为:2022年01月27日 02:15:56
线程二当前的时间为:2022年01月27日 02:15:56
线程一当前的时间为:2022年01月27日 02:15:57
线程二当前的时间为:2022年01月27日 02:15:57
线程二当前的时间为:2022年01月27日 02:15:58
线程一当前的时间为:2022年01月27日 02:15:58
线程二当前的时间为:2022年01月27日 02:15:59
线程一当前的时间为:2022年01月27日 02:15:59
线程一当前的时间为:2022年01月27日 02:16:00
线程二当前的时间为:2022年01月27日 02:16:00

可以看到并没有严格遵循,这只是一件概率上的事情。

你可能感兴趣的:(Java,分类,java)