java启动线程的方法(java同时启动两个线程去执行)

   日期:2022-02-16     文章发布:文章发布    网络转载:生活号    
核心提示:定义和概述 Java中的线程分为两类,分别为daemon线程(守护线程〉和user线程(用户线程)。守护线程又称Daemon线程,运行在后台,看不见;用户线程运行在前台,看的见。 在JVM启动时会调用main函数,main函数所在的线程就是一个用户线程,其实在JVM内部同时-还启动了好多守护线程,比如垃圾回收线程。 Daemon线程是一种支持型线程,因为它主要被用作程序中后台调度以及支持性工作。这...
移动站源标题:http://mip.818114.com/news/item-160123.html

定义和概述

Java 中的线程分为两类,分别为daemon 线程(守护线程〉和user 线程(用户线程)。守护线程又称Daemon线程,运行在后台,看不见;用户线程运行在前台,看的见。

在JVM启动时会调用main 函数, main 函数所在的线程就是一个用户线程,其实在JVM内部同时-还启动了好多守护线程, 比如垃圾回收线程。

Daemon线程是一种支持型线程,因为它主要被用作程序中后台调度以及支持性工作。这意味着,当一个Java虚拟机中不存在非Daemon线程的时候,Java虚拟机将会退出,而不管当前是否有守护线程,也就是说守护线程是否结束并不影响JVM的退出。

实际上,在main线程运行结束后,JVM会自动启动一个叫作DestroyJavaVM 的线程,该线程会等待所有用户线程结束后终止JVM 进程。

在Tomcat的NIO实现NioEndpoint中会开启一组接受线程来接受用户的连接请求,以及一组处理线程负责具体处理用户请求,在默认情况下,接受线程和处理线程都是守护线程,这意味着当tomcat 收到shutdown 命令后并且没有其他用户线程存在的情况下tomcat 进程会马上消亡,而不会等待处理线程处理完当前的请求。

2 使用守护线程

在线程start之前,可以通过调用thread.setDaemon(true)将线程设置为Daemon线程。

守护线程有两种结束方式:

  1. 守护线程也具有自己的run();方法,当后台线程完成自己的run方法后,守护线程结束。
  2. 用户线程运行结束,守护线程自动结束。

3 测试案例

public class Daemon {
//启动该类,将会构造两条线程,main线程和一条子线程。
    public static void main(String[] args) throws InterruptedException {
        //测试非守护线程
        //可以看到,输出"main线程结束"之后,子线程还在继续输出,程序没有结束
//        test1();
        //测试守护线程
        //可以看到,输出"main线程结束"之后,子线程没有继续输出,程序结束
        test2();
    }

    
    public static void test1() throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                try {
                    Thread.currentThread().sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("子线程非守护线程");
            }
        });
        thread.start();
        Thread.currentThread().sleep(1000);
        System.out.println("main线程结束");
    }

    //测试守护线程
    public static void test2() throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                try {
                    Thread.currentThread().sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("子线程守护线程");
            }
        });
        thread.setDaemon(true);
        thread.start();
        Thread.currentThread().sleep(1000);
        System.out.println("main线程结束");
    }
}

复制代码

使用jps查看java进程,可以发现如果子线程是守护线程那么主线程结束,子线程也结束了;如果子线程不是守护线程那么主线程结束,子线程没有结束。

4 注意事项

Daemon线程被用作完成支持性工作,但是在Java虚拟机退出时Daemon线程中的finally块并不一定会执行,如下代码:

public class Daemon {
    public static void main(String[] args) {
        Thread thread = new Thread(new DaemonRunner(), "DaemonRunner");
        thread.setDaemon(true);
        thread.start();
    }

    static class DaemonRunner implements Runnable {
        @Override
        public void run() {
            try {
                SleepUtils.second(10);
            } finally {
                System.out.println("DaemonThread finally run.");
            }
        }
    }
}

复制代码

运行Daemon程序,可以看到在控制台上没有任何输出。main线程(非Daemon线程)在启动了线程DaemonRunner之后随着main方法执行完毕而终止,而此时Java虚拟机中已经没有非Daemon线程,虚拟机需要退出。Java虚拟机中的所有Daemon线程都需要立即终止,因此DaemonRunner立即终止,但是DaemonRunner中的finally块并没有执行。

在构建Daemon线程时,不能依靠finally块中的内容来确保执行关闭或清理资源的逻辑。

免责声明:本网部分文章和信息来源于互联网,本网转载出于传递更多信息和学习之目的,并不意味着赞同其观点或证实其内容的真实性,如有侵权请通知我们删除!(留言删除
 
 
更多>同类行业

同类新闻
最新资讯
最新发布
最受欢迎
网站首页  |  黄页  |  联系方式  |  信息  |  版权隐私  |  网站地图  |  API推送  |  网站留言  |  RSS订阅  |  违规举报  |  京ICP备2000095号