Java中Thread线程基本知识

最近刚好辞职休息闲来无事刚好总结一下Java多线程中是东西,于是先从基础开始否则根基不牢固其他的都是瞎搞;

一、Java中线程基本概念

至于什么是进程、什么是线程、进程与线程区别,多线程的好处之类的就不多说了,如有不明白的请放弃吧。

1.守护线程与用户线程

Java分为两种线程:用户线程(User Thread)和守护线程(DaemonThread);
用户线程(User Thread)就是我们日常开发中并且未设置的子线程,包括Java工程中主线程(MainThread)和Android中的UI线程;

守护线程(DaemonThread):指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因 此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止;

守护线程与用户线程的区别,二者唯一的不同之处就在于虚拟机的离开:如果 User Thread已经全部退出运行了,只剩下Daemon Thread存在了,虚拟机也就退出了。 因为没有了被守护者,Daemon也就没有工作可做了,也就没有继续运行程序的必要了。

2.线程创建与启动

Java中创建的线程常见的方式有:
1.继承Thread类重写run方法;
2.实现Runnable接口;
3.借助Callable和Futurn实现多线程;
当然Java团队也封装了许多多线程的工具类例如:Timer等;

Java启动(start)的线程的方式有:
1.Thread类中的start()方法;
2.Java中的线程池提供的api;

二、线程生命周期和状态

1、新建(New):

创建线程时通过new方法来创建,处于新建(new)状态的线程JVM已经在内存空间分配好内存空间,创建好还没有没有执行start方法的线程状态;

2、就绪(Runnable):

对已经new好的Thread进行start()方法之后,Java虚拟机会为其创建方法调用栈和程序计数器,此时线程并没有开始运行,只是表示该线程可以运行了,该线程这时所处状态为:就绪状态;
至于该线程何时开始运行,取决于JVM里线程调度器的调度。

3、运行(Running):

处于就绪状态的线程获得了CPU资源后,开始执行run方法的线程执行体,则该线程处于运行状态;
运行状态的线程下一步线程状态变化最为复杂,它随着CPU资源时间片等变量随时可能转变为阻塞状态、就绪状态和死亡状态。

4、阻塞(Blocked):

处于运行状态的线程,由于某些原因让出CPU并暂时停止自己的运行,等待再次运行(Running)的状态称为:阻塞状态;

  • 由运行状态转阻塞可能原因有:

  • 1.调用了sleep、yield、join方法;

  • 2.线程锁导致阻塞(object.wait 直到线程调用object.notify),
  • 3.等待网络 、I/O设备等资源,将让出CPU并暂时停止自己的运行,进入阻塞状态。

  • 在阻塞状态的线程不能进入就绪队列。只有当引起阻塞的原因消除时,如睡眠时间已到,或等待的I/O设备空闲下来,线程便转入就绪状态,重新到就绪队列中排队等待,被系统选中后从原来停止的位置开始继续运行。

5、死亡(Dead):

线程在run()方法执行结束后进入死亡状态。此外,如果线程执行了interrupt()或stop()方法,那么它也会以异常退出的方式进入死亡状态。

在网上看到不错线程生命周期状态图原文链接
这里写图片描述

三、线程优先级

线程的优先级是和操作系统相关联的,在操作系统中线程优先级较高的线程在抢占CPU资源时抢占到CPU资源的概率更大。在代码中设置线程的优先级有助于线程调度器更加合理快速的分配CPU资源。

1.Java线程优先级的划分设置;

在Java中线程的优先级由低到高按照:1-10分为10个等级;

Thread类中提供了静态方法setPriority(int newPriority)用于设置线程的优先级;

JavaJDK【1.8】中setPriority(int newPriority)源码:

    //JDK中预定义的3个常量优先级
  public final static int MIN_PRIORITY = 1;
  public final static int NORM_PRIORITY = 5;
  public final static int MAX_PRIORITY = 10;

  public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();//检查是否可以修改线程优先级
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {//如果设置优先级不在范围内就抛出参数异常
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {/*与线程组优先级相比较*/
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);/*通过native方法设置优先级*/
        }
    }

在JDK源码中可以看到开发者设置的线程优先级必须在1-10之间反之就抛出IllegalArgumentException;

在实际开发中可以根据场景的需要设置线程优先级,提高代码的质量和用户体验,不过这是一个技术活,设置不当可能适得其反;个人只用过在一些优先级低的Task中将线程的优先级设置的小于NORM_PRIORITY ,尽量降低和View线程抢占导致界面卡顿便于GC回收;

2.默认优先级

在Java中手动开启一下线程默认线程的优先级是NORM_PRIORITY 即为5;

Java中主Main线程和守护Daemon线程的默认优先级同样为NORM_PRIORITY 即为5;
Android中应用中采用Java编程的,所以Android主线程的优先级同样是NORM_PRIORITY

3.线程优先级的继承性

线程是继续性很好理解,类似Java的继承特性一样,即在子线程继承了父线程后,同时也继承了父线程的优先级;
估计很多人刚开始也就没用太多关注过这个继承性的,不过用起来也很简单,所以也什么多说的;

4.线程优先级的随机性

优先级的随机性其实是指:
线程在抢占资源时的随机性,即多个不同的优先级线程同时抢占CPU等计算机资源时具有随机性,简单的说就是不同的优先级线程抢占资源时并不是优先级高的线程就一定会先获取资源,而是获取资源的线程具有随机性;

刚看到这里可能会有人疑惑的是:随机性是不是和优先级相矛盾;
实际情况是多线程中优先级高的线程在抢占资源时获取资源的概率随着优先级而提升,并不是一定是优先级高的就一定优先获得资源;至于测试Demo一则过于简单二者网上都烂大街了;

参考文章/资料
《Java多线程编程核心技术》
Java线程的6种状态及切换(透彻讲解)

猜你喜欢

转载自blog.csdn.net/black_bird_cn/article/details/82658151