Java~线程优先级、6种线程状态、Daemon线程、构造线程的源码分析、线程的启动、中断

线程优先级
  • 线程优先级就是决定这个线程获得更多或者更少的处理器资源.
  • 操作系统采用时分的方式来调度线程
  • 给每个线程分配若干时间片,时间片用完了就切换另一个线程
  • 时间片的多少就决定了线程用到的处理器资源的多少
  • 线程优先级是线程的一个属性,通过setPriority()方法进行设置
  • 线程优先级有1-10个等级,默认等级是5,优先级越高分配到的资源越多
  • 对于频繁阻塞的线程(比如休眠、I/O操作等)一般需要更高的优先级,偏向计算的可以设置低优先级
  • 在不同的JVM或操作系统中,优先级情况可能不同,甚至会被直接忽略(我们的修改不起作用)
线程状态(6种)
  • NEW:初始状态,线程被构建,但是没有调用start方法
  • RUNNABLE:运行状态,Java将操作系统中的就绪和运行统称为“运行中”
  • BLOCKED:阻塞状态,表示线程阻塞于锁
  • WAITING:等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程的动作(通知/中断)
  • TIME_WAITING:超时等待,设置一个时间,超过这个时间就不等了,自行返回
  • TERMINATED:终止状态,线程执行完毕
  • 线程在声明周期中,不是固定在某个状态,而是随着代码的执行在不同状态之间切换

在这里插入图片描述

Daemon线程
  • Daemon线程是后台线程,当Java虚拟机中没有非后台线程的时候,虚拟机就会退出
  • Thread.setDaemon(true)将线程设置为Daemon线程
  • 如果要设置,必须在线程启动之前
  • 虚拟机退出时,所有后台线程会终止
  • 后台线程中的finally语句块不一定执行,所以不能在finally中关闭或者清理资源。比如下面代码就没有任何输出
public class Priority {
    public static void main(String[] args) {
        Thread thread = new Thread(new DaemonRunner(), "DaemonThread");
        thread.setDaemon(true);
        thread.start();
    }
    static class DaemonRunner implements Runnable {
        @Override
        public void run() {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println("DaemonThread finally run.");
            }
        }
    }
}    
启动终止一个线程
  • 调用start方法,线程启动,run方法执行完毕,线程终止

构造线程

  • 在Thread类源码中,构造一个线程对象会有一个对应的parent线程(就是父线程)进行空间分配
  • child线程(子线程)会继承父线程的各种属性,比如是否为Dameon后台、优先级情况、和可继承的ThreadLocal等
  • 会分配一个唯一ID标识子线程
  • 线程对象创建完毕会放在堆内存

启动线程

  • 调用start即可启动线程

中断线程

  • 每个线程都有一个中断标识位
  • 线程B可以调用线程A的interrupt方法来将线程A的中断标识设为true
  • interrupt方法只会改变线程的中断状态,并不会真正中断线程,需要线程自己来决定中断还是不中断,但有可以中断线程的方法,如sleep,wait,join等,这些方法会不断的监测中断状态,一旦中断状态是true,就会立即中断线程,并抛出异常。如果抛出中断异常,说明线程已经中断。
  • 线程可以通过isInterrupted()方法来判断线程是否已经中断
  • 线程可以通过调用静态方法Thread.interrupted()方法来对标识位进行复原
  • 一个线程终止后,无论有没有被中断过,调用这个线程的isInterrupted()都会返回false
  • 线程方法在抛出InterruptException之前都会先清除中断标记位,然后才抛出异常

比如下面两个线程,sleep和busy线程,明明都被中断过,sleep抛出异常前清除了标记位

  public static void main(String[] args)throws Exception {
        Thread sleep=new Thread(new SleepRunner(),"sleepThread");
        sleep.setDaemon(true);
        Thread busy=new Thread(new BusyRunner(),"BusyThead");
        busy.setDaemon(true);
        sleep.start();
        busy.start();
        TimeUnit.SECONDS.sleep(5);
        sleep.interrupt();
        busy.interrupt();
        System.out.println("sleep线程是否被中断过:"+sleep.isInterrupted());
        System.out.println("busy线程是否被中断过:"+busy.isInterrupted());
        TimeUnit.SECONDS.sleep(2);
    }
    static class SleepRunner implements Runnable{
        @Override
        public void run(){
            while(true){
                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    static class BusyRunner implements Runnable{
        @Override
        public void run(){
            while(true){

            }
        }
    }

sleep线程是否被中断过:false
busy线程是否被中断过:true
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at java.lang.Thread.sleep(Thread.java:340)
	at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
	at currentTest.Priority$SleepRunner.run(Priority.java:30)
	at java.lang.Thread.run(Thread.java:748)

终止线程

  • 终止线程有两个方法:调用该线程的interrupt方法、自己创建一个布尔变量控制线程
  • 前者调用线程isInterrupted方法可以检测出来,而后者手动创建布尔变量的方式能终止线程,但是isInterrupted方法检测不出来
public static void main(String[] args) throws Exception{
        Runner one =new Runner();
        Runner two=new Runner();

        Thread countThread=new Thread(one,"CountThread");
        countThread.start();
        //睡眠1秒 然后中断线程
        TimeUnit.SECONDS.sleep(1);
        countThread.interrupt();//main线程对countThread进行中断
        System.out.println(countThread.isInterrupted()); //true
        countThread=new Thread(two,"CountThread");
        countThread.start();
        TimeUnit.SECONDS.sleep(1);
        two.Canle();
        System.out.println(countThread.isInterrupted());
    }
    private static class Runner implements Runnable{
        private  long i;
        private volatile boolean on=true;
        @Override
        public void run(){
            while(on && !Thread.currentThread().isInterrupted()){
                i++;
            }
            System.out.println("Count i="+i);
            System.out.println("线程中止");
            System.out.println(Thread.currentThread().isInterrupted());
        }

        public  void Canle(){
            System.out.println("下面修改标记变量进行中断");
            on=false;
        }
    }


true
Count i=609041703
线程中止
true
下面修改标记变量进行中断
false
Count i=750220463
线程中止
false
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值