多线程三 线程的停止及守护线程

线程停止

      • 1. 线程的停止
        • 设置标志位
        • stop方法强行关闭线程
        • 调用Thread类提供的interrupt
      • 2. 线程的优先级
      • 3. 守护线程

1. 线程的停止

三种方式停止当前线程

  1. 设置标记位,线程正常退出
  2. 使用stop方法强制线程退出,该方法不安全已被弃用
  3. 使用interrupt方法中断线程

设置标志位

设置标志位(无法处理线程阻塞时的问题)

class TStop implements Runnable {
    //设置标志位
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag) {
            System.out.println(Thread.currentThread().getName() + "执行 i = " + (i++));
        }
    }

    //转换标志位
    public void setFlag() {
        this.flag = false;
    }
}

public class ThreadStop {
    public static void main(String[] args) throws InterruptedException {
        TStop tp = new TStop();
        Thread thread = new Thread(tp,"线程A");
        thread.start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("[main]->" + i);
            if (i == 900) {
                //thread.stop();不建议使用stop方法强制停止线程
                tp.setFlag();
                Thread.sleep(100);
                System.err.println("线程A执结束!");
            }
        }
    }
}

多线程三 线程的停止及守护线程_第1张图片

stop方法强行关闭线程

为什么说stop方法强行关闭线程不安全呢?

因为stop会解除由线程获取的所有锁,当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止

假如一个线程正在执行:

synchronized void { x = 3; y = 4;} 

由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到 x=3 时,被调用了stop方法,当前线程会被强制停止执行,导致y没有被赋值。即使在同步块中,它也会立即stop,这样就产生了不完整的残缺数据。


调用Thread类提供的interrupt

若线程中没有使用类似sleep/wait/join时(使线程进入阻塞态),调用此线程对象的interrupt 不会真正中断线程,只是简单的将线程的状态置为interrupt而已,根据此状态来进一步确定如何处理线程

class ThreadRupt implements Runnable {
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.err.println("收到中断信号!");
                e.printStackTrace();
                break;
            }
        }
    }
}

public class ThreadInterrupt {
    public static void main(String[] args) throws InterruptedException {
        ThreadRupt tr = new ThreadRupt();
        Thread thread = new Thread(tr);
        Thread.sleep(1000);
        thread.start();
        System.out.println("是否中断?"+ thread.isInterrupted());
        thread.interrupt();
        System.out.println("是否中断?"+ thread.isInterrupted());
    }
}

多线程三 线程的停止及守护线程_第2张图片

Thread类提供的isInterrupted方法,测试这个线程是否被中断

若线程中调用了阻塞线程的方法sleep/wait/join方法,此时再掉用线程的 interrupt方法会抛出异常,同时线程状态还原 isInterrupted = false

class MyThreadStop implements  Runnable {

    private boolean flag = true;
    
    @Override
    public void run() {
    int i = 0;
    while(flag) {
        try {
            Thread.sleep(1000);
            boolean bool = Thread.currentThread().isInterrupted();
            if(bool) {
                System.out.println("非阻塞情况!线程的中断状态: " + bool);
                break;
            }
            System.out.println("第" +i+ "次执行,线程名称为:" + Thread.currentThread().getName() + "执行 i = " + (i++));
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("线程中断……");
            System.out.println(Thread.currentThread().isInterrupted());
            //退出循环
            break;
        }
    }
    }
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

public class ThreadStop {
    public static void main(String[] args) throws InterruptedException {
        MyThreadStop threadStop = new MyThreadStop();
        Thread thread = new Thread(threadStop,"子线程A ");
        thread.start();
        Thread.sleep(5000);
        thread.interrupt();
        System.out.println("Main 方法执结束!");
    }
}
多线程三 线程的停止及守护线程_第3张图片

interrupt()源码:

interrupt0()为中断标志位
多线程三 线程的停止及守护线程_第4张图片

2. 线程的优先级

线程的优先级指的是优先级越高 越有可能被先执行

就拿买彩票来说,买100张彩票的中奖几率一定是大于一张的,但是买100张彩票就一定会中奖吗?搏一搏,单车变摩托?

同样的道理,线程的优先级越高,越有可能被先执行。执行的机率加大,但具体是否执行,还得看CPU的调度

多线程三 线程的停止及守护线程_第5张图片

  • 设置线程优先级 setPriority(int priority)

  • 获取优先级 int getPriority

JDK内置的三种优先级:

多线程三 线程的停止及守护线程_第6张图片

MAX_PRIORITYT = 10

NORM_PRIORITYT = 5

MIN_PRIORITYT = 1

main线程默认的优先级为 NORM_PRIORITYT = 5

优先级的设定: 优先级的设定要放到启动线程之前

线程的继承性: 在一个线程中创建了子线程,默认子线程与父线程的优先级相同

public class ThreadPriority implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " -->> " + Thread.currentThread().getPriority());
    }

    public static void main(String[] args) {
        System.out.println("[" + Thread.currentThread().getName() + "] 优先级为 -> " + Thread.currentThread().getPriority());
        ThreadPriority tp = new ThreadPriority();
        Thread t1 = new Thread(tp);
        Thread t2 = new Thread(tp);
        Thread t3 = new Thread(tp);
        Thread t4 = new Thread(tp);
        Thread t5 = new Thread(tp);
        t1.setPriority(Thread.MIN_PRIORITY);
        t1.start();

        t2.setPriority(3);
        t2.start();

        t3.setPriority(Thread.NORM_PRIORITY);
        t3.start();

        t4.setPriority(7);
        t4.start();

        t5.setPriority(Thread.MAX_PRIORITY);
        t5.start();
    }
}

理论上优先级高的先执行,但是还取决于CPU的调度
多线程三 线程的停止及守护线程_第7张图片
多线程三 线程的停止及守护线程_第8张图片


3. 守护线程

Java中线程分为:

  • 用户线程
  • 守护线程(Daemon)

守护线程为陪伴线程,只要JVM中存在任何一个用户线程没有终止,守护线程就一直在工作。JVM必须确保用户线程执行完毕,但是不用等待守护线程

默认创建的线程都是用户线程,包括主线程

通过setDaemon(true)将线程对象设置为守护线程

典型的守护线程:垃圾回收线程、内存监控、日志记录

class God implements Runnable {
    @Override
    public void run() {
        while (true) {
            System.out.println("God Bless you!");
        }
    }
}

class Person implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Live happily...");
        }
        System.err.println("--> 撒由那拉!!!");
    }
}

public class ThreadDaemon {
    public static void main(String[] args) throws InterruptedException {
        God god = new God();
        Person per = new Person();
        Thread thread = new Thread(god);
        //设置上帝为守护线程
        thread.setDaemon(true);
        thread.start();
        new Thread(per).start();
    }
}

当用户线程Person结束后,守护线程并没有立即停止
多线程三 线程的停止及守护线程_第9张图片

你可能感兴趣的:(#,JavaSE,线程的停止,线程的中断,interrupt(),守护线程)