线程的生命周期及方法

回顾

 * 进程:一段正在运行的程序,资源分配的基本单位
 * 线程:进程中的任务,cpu调度的最小单元
 * 线程的创建:
 * 1)Thread 继承
 * 2)Runnable 实现
 * 3)Callable 实现
 * 4)匿名内部类
 * 启动线程:start (run call)
 *
 * 守护线程
 * 守护线程是一类比较特殊的线程,一般用于处理后台的工作,比如JDK的垃圾回收线程
 * 什么守护线程?为什么会有守护线程?何时需要守护线程?
 * 明确:JVM什么情况下退出?
 * The java virtual machine exits when the only thread running are
 * all dameon thread.
 * 如果JVM没有一个守护线程,JVM进程不会退出
 * 守护线程具备自动结束生命周期的特点,非守护线程不具备这样的特点
 * eg. 如果垃圾回收线程是一个非守护线程,那么某一程序完成工作运行结束,JVM无法退出,
 * 垃圾回收线程依旧工作
 *
 * 例:使用匿名线程的方式创建一个线程,这个线程持续睡眠1ms,主线程睡眠1000ms输出
 * 主线程main结束
 *
 * 注意:setDaemon方法只能线程启动之前使用,如果对于一个线程已经死亡或者未
 * 启动,那么设置setDaemon会抛出IllegalThreadStateException
 *
 * 并发与并行概念
 * 并发指的是多个线程操作同一个资源,不是同时执行,而是交替执行,单核cpu,只不过
 * cpu时间片很短,执行速度很快,看起来同时执行
 *
 * 并行才是真正的同时执行,多核cpu。每一个线程使用一个单独的cpu运行
 *
 * QPS: 每秒能够响应的请求数
 * 吞吐量: 单位时间内能够处理的请求数
 * 平均响应时间: 系统对某一个请求的平均响应时间 QPS = 并发数/平均响应时间
 * 并发用户数: 系统可以承载的最大用户数
 *
 * 互联网系统结构如何提高系统的并发能力?
 * 垂直方向
 * 水平方向(集群(多个做同一件事) 分布式(一个复杂的事情拆分去做))
 */
public class TestDemo3 {
    
    
    public static void main(String[] args) {
    
    
        //匿名线程
        Thread thread = new Thread(){
    
    
            @Override
            public void run() {
    
    
                while(true){
    
    
                    try {
    
    
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }
            }
        };
        //设置thread为守护线程
        thread.setDaemon(true);
        thread.start();
        /**
         * thread是一个非守护线程,main线程正常运行结束之后,JVM进程并没有退出;
         * 如果我们将thread设置为守护线程,main线程结束生命周期,JVM进程退出
         *
         */
        //睡眠 Thread.sleep(1000)
        try {
    
    
            Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        //sout
        //main线程结束
        System.out.println("main thread finished");
    }
}

线程生命周期

	 * new(新建状态) new关键字创建一个线程对象,它并不是处于一个执行状态,因为还没有start
	 * 启动线程
	 * Runnable(就绪状态) 线程对象调用start方法,才是在JVM中真正创建了一个线程,线程一经启动
	 * 并不会立即执行,该状态的所有线程位于就绪线程池中,等待操作系统的资源,如:处理器,获得
	 * cpu的使用权
	 * Blocked(阻塞状态) 等待一个监视器锁进入同步代码块或者同步方法,代码块/方法某一时刻只能够
	 * 有一个线程执行,其他线程只能等待
	 * Waiting(等待状态) Object.wait()/Thread.join()/LockSupport.park()都会使得线程阻塞,
	 * 从Runnable转换到Waiting状态
	 * Timed_Waiting(睡眠状态) 调用加超时参数的Object.wait(long mills)/Thread.slepp(long mills)/LockSupport.
	 * parkNano()/LockSupport.parkUntil()
	 * Terminated(终止状态) 是一个线程的最终状态,线程进入到Terminated状态,意味着该线程的生命周期结束了,下面这些情况都会使得线程进入Terminated状态
	 * 1)线程执行正常结束
	 * 2)线程运行出错意外结束
	 * 3)JVM crash
	 将这些场景比作一次跑步比赛![在这里插入图片描述](https://img-blog.csdnimg.cn/20210202203441634.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NzE5ODU2MQ==,size_16,color_FFFFFF,t_70)

 * 线程中常用方法
 * 1)start()
 * 启动一个线程,将线程添加一个线程组中,线程状态会从New状态转换到Runnable状态,然后获取
 * Cpu之后进入Running状态执行run
 * 2)sleep()
 * sleep是一个静态方法,其中存在两个重载函数
 * public static native void sleep(long millis)
 * public static void sleep(long millis, int nanos)
 * 使得线程进入睡眠状态,暂停执行,sleep不会放弃monitor lock的所有权
 * jdk1.5之后,jdk引入一个枚举TimeUnit,其对sleep方法做了封装,直接使用从而时间单位
 * 换算的步骤,比如线程睡眠3h27min8sec88msec
 * 3)yield()
 * yield表示提醒cpu调度器我愿意放弃当前的cpu资源,(属于启发式方法),如果cpu资源不紧张
 * 的情况下,会忽略这种提示
 * 面试题:yield和sleep的区别
 * a.jdk1.5之前,yield调用了sleep
 * b.sleep使得当前线程暂停执行,不会占用cpu资源
 *  yield只是对于cpu调度器的一个提示
 * c.sleep会导致线程短暂的阻塞,yield会使得线程Runnable-》Runnable
 * d.sleep会捕获到中断异常,yield不会捕获到中断异常
 *
 * 4)join()
 * 含义:在线程B中join某个线程A,会使得B线程进入等待,直到线程A结束生命周期,或者达到给定的时间,
 * 在这期间线程B会处于等待状态
 * 课堂练习:
 * ThreadA打印1-10, ThreadB打印打印1-10,,ThreadC打印1-10, 保证按照A->B->C顺序打印
 * 5)wait()
 * 6)notify()
 * 7)notifyAll()
 * 8)线程中断方法

A,B,C三个线程 使得A,B,C三个线程顺序打印1~10
join方法的应用:

class ThreadDemo extends Thread{
    
    
    private Thread thread;
    private String name;

    public ThreadDemo(Thread thread, String name){
    
    
        this.name = name;
        this.thread = thread;
    }
    @Override
    public void run() {
    
    
        if(thread != null){
    
    
            try {
    
    
                thread.join();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
        for(int i=1; i<=10; i++){
    
    
            System.out.println(name +"::" +i);
        }
    }
}
public class TestDemo4 {
    
    
    public static void main(String[] args) {
    
    
        //A,B,C三个线程  使得A,B,C三个线程顺序打印1~10
        ThreadDemo A = new ThreadDemo(null, "线程A");
        ThreadDemo B = new ThreadDemo(A, "线程B");
        ThreadDemo C = new ThreadDemo(B, "线程C");
        A.start();
        B.start();
        C.start();

    }
}

TimeUnit使用

        new Thread(()->{
    
    
            try {
    
    
                //Thread.sleep(5000);
                TimeUnit.HOURS.sleep(3);
                TimeUnit.MINUTES.sleep(27);
                TimeUnit.SECONDS.sleep(8);
                TimeUnit.MILLISECONDS.sleep(88);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        });

线程方法

 * wait 调用某个对象的wait()方法可以让当前线程阻塞
 * notify        调用当前对象notify/notifyAll才能够唤醒这个对象所在的线程
 * notifyAll
 * 注意:使用这三个方法需要让当前线程拥有当前对象的monitor lock
 *
 * 线程中断方法
 * 每个Java线程都会有一个中断状态位,程序可以检测这个中断状态位判读线程是否执行结束
 *
 * a.interrupt()
 * public void interrupt() 由线程对象调用,将中断位置置为true
 *
 * 如下方法能够使得当前线程进入阻塞状态,调用interrupt方法可以打断阻塞,因此这种
 * 方法被称之为可中断方法
 * Object.wait()/wait(long)
 * Thread.sleep(long)/TimUnit.XXX.sleep(long)
 * Thread.join()/Thread.join(long)
 *
 * interrupt
 * 如果一个线程被interrupt,设置interrupt flag;如果当前线程正在执行可中断方法,调用
 * interrupt方法,反而导致interrupt flag被清除
 *
 * b.isInterrupted判断当前线程的中断状态位是否为true
 *
 * c.interrupted
 * public static Boolean interrupted() 静态方法
 * 调用interrupted会擦除中断状态位的标识

*/

这是wait和notify的应用

        new Thread("A"){
    
    
            @Override
            public void run() {
    
    
                synchronized (strs){
    
    
                    //同步代码块
                    try {
    
    
                        strs.wait(); //释放当前对象的monitor lock -》Waiting
                        //表示让当前线程进入到阻塞状态
                        System.out.println("the currend thread name is "+Thread.currentThread().getName());
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }
            }
        }.start();


        new Thread("B"){
    
    
            @Override
            public void run() {
    
    
                synchronized (strs){
    
    
                    //strs.notify();//随机唤醒其中一个
                    strs.notifyAll(); //唤醒所有线程 然后所有线程开始抢锁
                }
            }
        }.start();

这是interrupt的应用

public class TestDemo5 {
    
    
    public static void main(String[] args) {
    
    
        Thread thread = new Thread(){
    
    
            @Override
            public void run() {
    
    
                while(true){
    
    
                    System.out.println(Thread.interrupted());
                }
            }
        };
        thread.setDaemon(true);
        thread.start();

        try {
    
    
            TimeUnit.MILLISECONDS.sleep(2);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        thread.interrupt();
public class TestDemo5 {
    
    
    public static void main(String[] args) {
    
    
        Thread thread = new Thread(){
    
    
            @Override
            public void run() {
    
    
                while(true){
    
    
                    try {
    
    
                        TimeUnit.MILLISECONDS.sleep(1); //sleep会擦除中断状态位
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }
            }
        };
        thread.start();
        try {
    
    
            TimeUnit.MILLISECONDS.sleep(200);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println("Thread is interrupted: "+thread.isInterrupted());
        thread.interrupt();
        System.out.println("Thread is interrupted: "+thread.isInterrupted());
        Thread thread = new Thread(){
    
    
            @Override
            public void run() {
    
    
                try {
    
    
                    TimeUnit.SECONDS.sleep(10); //使得子线程进入阻塞状态
                    //interrupt方法会打断这种阻塞,会抛出异常
                } catch (InterruptedException e) {
    
    
                    System.out.println("I am be interrupted");
                }
            }
        };
        thread.start();

        try {
    
    
            TimeUnit.MILLISECONDS.sleep(200);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        thread.interrupt();
        Thread thread = new Thread(){
    
    
            @Override
            public void run() {
    
    
                while(true){
    
    
                    System.out.println("test interrupt");
                    try {
    
    
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
    
    
                        //e.printStackTrace();
                        System.out.println(Thread.currentThread().isInterrupted());
                    }
                }
            }
        };
        thread.start();
        thread.interrupt(); //将thread的中断状态位置为true
        System.out.println("Thread interrupt flag: "+thread.isInterrupted());
        sleep 可中断方法能够清除原本线程置为true的中断状态位
        String strs = new String("test wait");

猜你喜欢

转载自blog.csdn.net/weixin_47198561/article/details/113555684
今日推荐