线程的挂起与恢复案例详解

什么是挂起线程?

线程的挂起操作实质上就是使线程进入“非可执行”状态下,在这个状态下CPU不会分给线程时间片,进入这个状态可以用来暂停一个线程的运行。在线程挂起后,可以通过重新唤唤醒线程来使之回服运行

为什么要挂起线程?

CPU分配的时间片非常短、同时也非常珍贵。避免资源的浪费

如何挂起线程?

被废弃的方法thread.supend()该方法不会释放线程所占用的资源,如果使用该方法将某个线程挂起,则可能会使其它等待资源的线程锁死
thread.resume()方法本身并无问题,但是不能独立于supend()方法存在
可以使用方法wait()暂停执行、放弃已经获得的锁、进入等待状态
notify():随机唤醒一个等待锁的线程
notifyAll():唤醒所有等待锁的线程,自行抢占cpu资源

supend和resume方法演示

实际开发中不要使用这两个方法,源码中注解@Deprecated表示已经被废弃了 问题不会释放线程所占资源,可能出现死锁

/**
 * Supend方法挂起操作Demo
 */
public class SupendDemo implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"执行run方法,准备调用supend方法");
        //挂起线程
        Thread.currentThread().suspend();
        System.out.println(Thread.currentThread().getName()+"执行run方法,调用supend方法结束");
    }

    public static void main(String [] args) throws InterruptedException {
        Thread thread = new Thread(new SupendDemo());
        thread.start();
        thread.sleep(3000L);
        //3秒后对线程进行唤醒操作
        thread.resume();
    }
}

死锁案例

死锁线程并没有释放资源

产生的原因:程序运行过快,线程还没挂起就去唤醒,所以导致不会释放资源的问题,除非线程睡眠

/**
 * supend 死锁演示
 */
public class DeadDemo implements Runnable{

    private static Object object = new Object();

    @Override
    public void run() {

        //持有资源
        synchronized (object){
            System.out.println(Thread.currentThread().getName()+"占用资源");
            Thread.currentThread().suspend();
        }
        System.out.println(Thread.currentThread().getName()+"释放资源");
    }

    public static void main(String [] args) throws InterruptedException {
        Thread thread = new Thread(new DeadDemo(),"对比线程");
        thread.start();
        Thread.sleep(3000L);
        thread.resume();

        Thread thread2 = new Thread(new DeadDemo(),"死锁线程");
        thread2.start();
        //Thread.sleep(3000L);
        thread2.resume();
    }
}

在这里插入图片描述

wait()nofity()案例

/**
 * wait挂起 notify唤醒案例
 */
public class WaitDemo implements Runnable {


    private static Object object = new Object();

    private static Object waitObj = new Object();

    @Override
    public void run() {

        //持有资源
        synchronized (waitObj){
            System.out.println(Thread.currentThread().getName()+"占用资源");
            try {
                waitObj.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName()+"释放资源");
    }

    public static void main(String [] args) throws InterruptedException {


        Thread thread = new Thread(new WaitDemo(),"对比线程");
        thread.start();
        Thread.sleep(3000L);
        synchronized (waitObj){
            waitObj.notify();
        }

    }
}

什么时候适合使用挂起线程?

我等的船还不来(等待某些未就绪的资源,可以先将线程挂起,让出时间片)

直到notify被调用 唤醒线程,避免无谓的资源浪费

猜你喜欢

转载自blog.csdn.net/q736317048/article/details/113797764