JAVA多线程-(二)线程的生命周期和线程的“打断”

线程的生命周期

1.生命周期
一个线程从创建,到最终的消亡,需要经历多种不同的状态,而这些不同的线程状态,由始至终也构成了线程生命周期的不同阶段。线程的生命周期可以总结为下图。
其中,几个重要的状态如下所示。

  • NEW:初始状态,线程被构建,调用new Thread(),但是还没有调用start()方法。
  • RUNNABLE:可运行状态,可运行状态可以包括:运行中状态和就绪状态,就绪状态是调用了start()方法,但是没有获取CPU资源,等待获取CPU资源的状态,一旦获取了CPU资源线程调度器开始调度就会开始执行run()方法这时候就会变为运行中状态。
  • BLOCKED:阻塞状态,需要获取synchronized锁,但是没有获取到,被别的线程获取到,就会处于阻塞状态。处于这个状态的线程需要等待其他线程释放锁或者等待进入synchronized。
  • WAITING:表示等待状态,当前正在运行的线程调用object.wait()Thread.join(),LockSuppore.park()就会进入waiting等待状态,处于该状态的线程需要等待其他线程对其进行通知或中断等操作,进而进入下一个状态。
  • TIME_WAITING:超时等待状态。可以在一定的时间自行返回。
  • TERMINATED:终止状态,当前线程执行完毕。
    在这里插入图片描述
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * title:${file_name}
 * 关于线程状态的实验
 *
 * @version 2.0
 * @date ${date}
 */

public class T04_ThreadState {

    public static void main(String[] args) throws Exception {
        //===================================================
        Thread t1 = new Thread(() -> {
            System.out.println("2: " + Thread.currentThread().getState());//RUNNABLE
            for (int i = 0; i < 3; i++) {
                SleepHelper.sleepSeconds(1);
                System.out.print(i + " ");//0 1 2
            }
            System.out.println();//run执行结束标志t1线程执行结束
        });
        System.out.println("1: " + t1.getState());// NEW
        t1.start();
        t1.join();//阻塞主线程,T1线程先执行run方法,T1执行完毕再执行后面的
        System.out.println("3: " + t1.getState());//TERMINATED 终止

        //===================================================
        Thread t2 = new Thread(() -> {
            try {
                LockSupport.park();//让t2自己阻塞
                System.out.println("t2 go on!");
                TimeUnit.SECONDS.sleep(5);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t2.start();//运行t2开始 准备被调度执行
        TimeUnit.SECONDS.sleep(1);//主线程休眠 t2肯定会执行 
        System.out.println("4: " + t2.getState());//LockSupport.park();让t2等待变为waiting状态

        LockSupport.unpark(t2);//唤醒T2 t2继续执行run方法LockSupport.park()后的内容 输出t2 go on! 然后t2休眠5秒
        TimeUnit.SECONDS.sleep(1);//主线程休眠
        System.out.println("5: " + t2.getState());//t2唤醒之后又调用sleep(5)方法 ,指定时间5秒, 所以会timed waiting

        //===================================================
        final Object o = new Object();
        Thread t3 = new Thread(() -> {
            synchronized (o) {
                System.out.println("t3 getLock o");
            }
        });//只是new t3线程此时是new状态 没调用start方法,不会等待执行

        new Thread(() -> {
            synchronized (o) {
                System.out.println("wait 5s start");
                SleepHelper.sleepSeconds(5);
                System.out.println("wait 5s end");
            }
        }).start();//调用start方法,准备调度获得执行机会

        SleepHelper.sleepSeconds(1);//主线程休眠1秒 上面new Thread会执行,竞争成功,获取synchronized关键字  输出wait 5s start   
        // 然后休眠5秒 输出wait 5s end 释放抢占资源  T3运行start方法之后才有机会获取synchronized关键字 执行方法 输出t3 getLock o

        t3.start();
        SleepHelper.sleepSeconds(1);//主线程休眠1秒
        System.out.println("6: " + t3.getState());//此时还在等待System.out.println("wait 5s start");
        //SleepHelper.sleepSeconds(5); 这个5秒走完获取synchronized关键字  此时是BLOCKED状态 等待获取synchronized

        //===================================================
        final Lock lock = new ReentrantLock();
        Thread t4 = new Thread(() -> {
            lock.lock(); //省略try finally
            System.out.println("t4 getLock o");
            lock.unlock();
        });

        new Thread(() -> {
            lock.lock();
            SleepHelper.sleepSeconds(5);
            lock.unlock();
        }).start();

        SleepHelper.sleepSeconds(1);//主线程休眠 上面线程调度执行 等待5秒释放lock锁 

        t4.start();
        SleepHelper.sleepSeconds(1);//主线程休眠 t4等待上面线程释放lock锁 等待执行 
        System.out.println("7: " + t4.getState());//等待获取lock,所以是WAITING

        //===================================================
        Thread t5 = new Thread(() -> {
            LockSupport.park();
        });

        t5.start();

        SleepHelper.sleepSeconds(1);//t5执行 LockSupport.park()阻塞自己线程 

        System.out.println("8: " + t5.getState()); //WAITING状态
        LockSupport.unpark(t5);//释放 

    }
}
//yield 让出去一下,等待线程调度器再次随机调度 还可能调到自己

1: NEW
2: RUNNABLE
0 1 2
3: TERMINATED
4: WAITING
t2 go on!
5: TIMED_WAITING
wait 5s start
6: BLOCKED
7: WAITING
wait 5s end
t3 getLock o
8: WAITING
t4 getLock o

2.线程的“打断”

• interrupt()
打断某个线程(设置标志位)
• isInterrupted()
查询某线程是否被打断过(查询标志位)
• static interrupted()
查询当前线程是否被打断过,并重置打断标志
isInterrupted()和interrupt()

/**
 * interrupt()与isInterrupted()
 * 设置标志位 + 查询标志位
 * • interrupt()
 * • 打断某个线程(设置标志位)
 * • isInterrupted()
 * • 查询某线程是否被打断过(查询标志位)
 * • static interrupted()
 * • 查询当前线程是否被打断过,并重置打断标志
 */
public class T05_Interrupt_and_isInterrupted {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            for (; ; ) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("Thread is interrupted!");
                    System.out.println(Thread.currentThread().isInterrupted());
                    break;
                }
            }
        });

        t.start();

        SleepHelper.sleepSeconds(2);

        t.interrupt();
    }
}

/*
 * 先new一个Thread对象
 * t.start();  线程准备启动,等待CPU给资源
 * SleepHelper.sleepSeconds(2); 主线程阻塞 这时候t运行 因为
 * Thread.currentThread().isInterrupted()查询是否设置标志位,如果没有设置不执行if
 * 等主线程sleep结束,等获取到资源开始运行 当执行 t.interrupt(); 设置标志位 这时候t线程开始
 * 进入if里边的代码块  输出 Thread is interrupted!   true
 * break跳出for循环 程序结束
 *
 * */

输出结果:

Thread is interrupted!
true

interrupted()和interrupt()
interrupted 查询当前线程是否被打断过,并重置打断标志

/**
 * interrupt与interrupted()
 * • interrupt()
 * • 打断某个线程(设置标志位)
 * • isInterrupted()
 * • 查询某线程是否被打断过(查询标志位)
 * • static interrupted()
 * • 查询当前线程是否被打断过,并重置打断标志
 */
public class T06_Interrupt_and_interrupted {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            for (; ; ) {
                if (Thread.interrupted()) {//查询当前线程是否被打断过,并重置打断标志
                    System.out.println("Thread is interrupted!");
                    System.out.println(Thread.interrupted());//查询当前线程是否被打断过,并重置打断标志
                }
            }
        });

        t.start();

        SleepHelper.sleepSeconds(2);

        t.interrupt();//打断某个线程(设置标志位)
      //  Thread.currentThread().interrupt();
        //思考一下,如果在这里写
         System.out.println("main: " + t.interrupted());//查询当前线程是否被打断过,并重置打断标志
        // 所以这里输出的是当前main线程 因为main线程没有调用设置标志位 所以输出false  如果输出前面调用Thread.currentThread().interrupt();设置标志位 那么这里就输出true
        //输出的是哪个线程的中断状态
    }
}

Thread is interrupted!
false
main: true

Interrupt_and_sleep
interrupt与sleep() wait() join() 可以设置标志位 会抛出异常 可以catch异常 catch异常之后标志位会复位 主动权给线程本身

/**
 * interrupt与sleep() wait() join()  可以设置标志位 会抛出异常  可以catch异常 catch异常之后标志位会复位  主动权给线程本身
 */
public class T07_Interrupt_and_sleep {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {//捕获异常 标志位复位
                System.out.println("Thread is interrupted!");
                System.out.println(Thread.currentThread().isInterrupted());
            }
        });

        t.start();

        SleepHelper.sleepSeconds(5);

        t.interrupt();//调用这个方法会打断t线程内的sleep方法 提前结束休眠
    }
}

Thread is interrupted!
false

Interrupt_and_wait
interrupt与sleep() wait() join() 可以设置标志位 会抛出异常 可以catch异常 catch异常之后标志位会复位 主动权给线程本身

/**
 * interrupt与sleep() wait() join()
 */
public class T08_Interrupt_and_wait {

    private static Object o = new Object();

    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            synchronized (o) {
                try {
                    o.wait();
                } catch (InterruptedException e) {
                    System.out.println("Thread is interrupted!");
                    System.out.println(Thread.currentThread().isInterrupted());
                }
            }
        });

        t.start();

        SleepHelper.sleepSeconds(5);

        t.interrupt();//打断t线程的wait等待
    }
}

Thread is interrupted!
false

Interrupt_and_sync
设置标志位 不会中断抢锁过程 线程之间锁的竞争不会受标志位中断的影响

/**
 * interrupt与sleep() wait() join()
 */
public class T09_Interrupt_and_sync {

    private static Object o = new Object();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            synchronized (o) {
                SleepHelper.sleepSeconds(10);
            }
        });

        t1.start();

        SleepHelper.sleepSeconds(1);

        Thread t2 = new Thread(() -> {
            synchronized (o) {

            }
            System.out.println("t2 end!");
        });

        t2.start();

        SleepHelper.sleepSeconds(1);

        t2.interrupt();//t2在等t1休眠10秒释放锁 即使这个时候对t2标志位进行修改 也不会中断干扰抢锁过程
    }
}
//设置标志位 不会中断抢锁过程

t2 end!

Interrupt_and_lock
设置标志位 不会中断抢lock锁过程

import java.util.concurrent.locks.ReentrantLock;

/**
 * interrupt与sleep() wait() join()
 */
public class T10_Interrupt_and_lock {

    private static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            System.out.println("t1 end!");
        });

        t1.start();

        SleepHelper.sleepSeconds(1);


        Thread t2 = new Thread(() -> {
            lock.lock();
            try {
            } finally {
                lock.unlock();
            }
            System.out.println("t2 end!");
        });

        t2.start();

        SleepHelper.sleepSeconds(1);

        t2.interrupt();//不会中断t2的获取ReentrantLock锁状态
    }
}

t1 end!
t2 end!

Interrupt_and_lockInterruptibly

import java.util.concurrent.locks.ReentrantLock;

/**
 * interrupt与lockInterruptibly()
 */
public class T11_Interrupt_and_lockInterruptibly {

    private static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                SleepHelper.sleepSeconds(10);
            } finally {
                lock.unlock();
            }
            System.out.println("t1 end!");
        });

        t1.start();

        SleepHelper.sleepSeconds(1);


        Thread t2 = new Thread(() -> {
            System.out.println("t2 start!");
            try {
                lock.lockInterruptibly();//可以被打断的过程 抢锁过程中如果该线程的标志位被改变会抛出异常
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            System.out.println("t2 end!");
        });

        t2.start();

        SleepHelper.sleepSeconds(1);

        t2.interrupt();//会中断t2的lock.lockInterruptibly(); 直接进入catch块捕获异常 执行finally  不执行别的

    }
}

t2 start!
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at com.mashibing.juc.c_000_threadbasic.T11_Interrupt_and_lockInterruptibly.lambda$main 1 ( T 1 1 I n t e r r u p t a n d l o c k I n t e r r u p t i b l y . j a v a : 33 ) a t j a v a . l a n g . T h r e a d . r u n ( T h r e a d . j a v a : 748 ) E x c e p t i o n i n t h r e a d " T h r e a d − 1 " j a v a . l a n g . I l l e g a l M o n i t o r S t a t e E x c e p t i o n a t j a v a . u t i l . c o n c u r r e n t . l o c k s . R e e n t r a n t L o c k 1(T11_Interrupt_and_lockInterruptibly.java:33) at java.lang.Thread.run(Thread.java:748) Exception in thread "Thread-1" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock 1(T11InterruptandlockInterruptibly.java:33)atjava.lang.Thread.run(Thread.java:748)Exceptioninthread"Thread1"java.lang.IllegalMonitorStateExceptionatjava.util.concurrent.locks.ReentrantLockSync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
at com.mashibing.juc.c_000_threadbasic.T11_Interrupt_and_lockInterruptibly.lambda$main$1(T11_Interrupt_and_lockInterruptibly.java:37)
at java.lang.Thread.run(Thread.java:748)
t1 end!

LockSupport_interrupt

public class T05_InterruptAndPark {
    public static void main(String[] args) {

        Thread t = new Thread(() -> {
            System.out.println("1");
            LockSupport.park();
            System.out.println("2");
        });

        t.start();

        SleepHelper.sleepSeconds(5);

        t.interrupt();//打断park
    }

}

总结:

  • t.interrupt();//调用这个方法会打断t线程内的sleep方法 提前结束休眠;
  • t.interrupt();//打断t线程的wait等待;
  • t2.interrupt();//synchronized:t2在等t1休眠10秒释放锁 即使这个时候对t2标志位进行修改 也不会中断干扰抢锁过程.
  • t2.interrupt();//不会中断t2的获取ReentrantLock锁状态;
  • t2.interrupt();//会中断t2的lock.lockInterruptibly(); 直接进入catch块捕获异常 执行finally 不执行别的。
  • t.interrupt();//打断线程的LockSupport.park();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值