Java线程简介

2018-05-08  本文已影响0人  Lebens

主要是介绍一些线程相关的知识点,包括线程的生命周期,守护线程等,为后续的博客做一些铺垫。

什么是线程

关于什么是线程,网上一大堆的介绍:

相对于进程,线程是操作系统(OS)调度的最小执行单元

线程的特点,根据线程的官方介绍可以看出:

  1. java应用可以同时执行多个线程
  2. 每个线程都有优先级,优先级高的线程优先于低优先级的线程执行
  3. 线程在创建时可以设置为守护线程
  4. 虚拟机启动时会有一个非守护线程的,也就是main方法所在的线程
  5. 当一个应用程序所有的非守护线程死亡时,jvm退出,同时所有守护线程被销毁
  6. 线程的创建有2种方式:继承Thread类并覆写run方法;在构造时传入一个Runnable实现类参数
  7. 每个线程都有一个名字用于标识线程

几个点需要说一下:

  1. 当设置一个线程为守护线程时,只能在调用Start()方法前设置,否则抛出异常
  2. 线程优先级分为1-10,默认为5
  3. 死亡的线程无法再次被运行

线程的生命周期

线程的生命周期分为新建状态就绪状态运行状态阻塞状态死亡状态 5种状态,这5种状态的转换如下图所示:

线程生命周期图.jpeg
  1. 调用new关键字,新建一个Thread实例对象有,实例对象就处于新建状态。
  2. 当Thread实例对象调用start()后,进入就绪状态可以被cpu调度执行。
  3. 就绪状态的Thread实例对象,在获取到cpu执行权后就可以运行。同时由于cpu的切换或者调用了线程的yield方法,会导致运行状态的Thread回到就绪状态。
  4. 当运行状态的线程遇到如下几种情况时将进入阻塞状态
    • wait()
    • sleep()
    • join()
    • 等待同步锁
    • 阻塞式I/O调用
  5. 阻塞状态的线程恢复进入就绪状态,当然在阻塞时线程被中断,那么线程进入死亡状态。
  6. 运行状态的线程正常运行完毕或者中断异常都将进入死亡状态。

守护线程

相对于正常线程,也就是所谓的用户线程来说,守护线程主要是用于为用户线程提供便利,这也是守护这个词的含义,最典型的就是java系统的GC线程。

当所有用户线程退出时,守护线程就没有服务对象也没有存在的意义,所以随着jvm的退出,所有的守护线程都会被销毁,这也就是java文档的说明。

关于守护线程有如下几个注意点:

  1. 设置守护线程必须在线程start()之前
  2. 守护线程里执行的代码存在不完整执行的风险,所以涉及到数据计算保存的,需要有明确结果的操作不宜放在这里执行
  3. 在守护线程下新建的线程也为守护线程

关于第一点限制也很好理解,当你把启动的用户线程设置为守护线程时,可能刚好把唯一的用户线程消灭了,然后jvm退出了,导致了第二点的问题。

举个例子验证一下上面说的,所有用户线程退出后jvm退出导致守护线程销毁的说法:

public class ThreadTest {

    public static void main(String[] args) {

        try {
            Thread thread = new Thread() {
                @Override
                public void run() {
                    try {
                        int i = 0;
                        while (true) {
                            System.out.println(i++);
                            Thread.sleep(200);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            thread.setDaemon(true);
            thread.start();
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

打印结果如下:

0
1
2
3
4

Process finished with exit code 0

结果也很明显,每200毫秒打印一个数字,等主线程sleep结束就退出了。

如果把thread.setDaemon(true);注释调可以看到,线程一直会打印到底。

总结

  1. 线程有5种状态:新建状态就绪状态运行状态阻塞状态死亡状态
  2. 线程有2种创建方式
  3. 线程有优先级
  4. 线程有名字
  5. 守护线程需要在start()之前指定
  6. 守护线程代码可能执行不完整
  7. 守护线程下新建的都是守护线程
上一篇下一篇

猜你喜欢

热点阅读