线程状态概述与等待唤醒案例分析

线程状态概述

线程从创建到运行到结束是一个线程的生命周期,当线程被创建到结束过程中,不是一直处于运行状态的,下面来介绍一下线程从运行到结束所有的状态.

接下来看一下详细图解:

 

 

sleep与wait
sleep(time):线程睡眠,让线程睡眠指定的毫秒数,在线程睡眠过程中,该线程是不会释放锁对象的,也可以说sleep(time)是个自私的,在该线程睡眠时间结束之后,锁对象才会被释放.
wair(time):线程等待,在线程等待过程中呢,会释放锁,较sleep而言,比较无私,在释放了锁对象之后,设置的时间超时,该线程不会继续往下执行了,需要重新获取锁对象才能继续执行,否则原地等待,如果没有抢到锁,该线程会进入锁阻塞的状态.
或者,wait(time)中途被notify(唤醒),需要重新获取锁对象,如果抢到锁了,会继续执行,如果没有抢到锁,该线程会进入锁阻塞的状态.

等待与唤醒
wait与notify
两个都是Object类中的方法,这两个方法必须在同一个锁对象中,
wari一旦进入无限等待状态,会释放锁,往后背notify唤醒之后,也需要重新抢锁,抢到了,继续执行,抢不到,锁阻塞.

notify唤醒一条等待的线程,如果有多个线程需要被唤醒,notify会在其中随机唤醒一个.

 public class MyThread {
    public static void main(String[] args) {
        //创建集合
        ArrayList<String> list = new ArrayList<>();

        //创建存数据的线程

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    synchronized (list){
                        //判断集合中有没有元素
                        if (list.size()!=0){
                            //线程等待
                            try {
                                list.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        //添加元素
                        list.add("张三");
                        System.out.println(list);

                        //唤醒取数据的线程
                        list.notify();
                    }
                }
            }
        }).start();

        //创建取数据的线程

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    synchronized (list){
                        //判断集合中有没有元素
                        if (list.size()==0){
                            //线程等待
                            try {
                                list.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }

                        //获取元素
                        list.remove(0);
                        System.out.println(list);

                        //唤醒存数据的线程
                        list.notify();
                    }
                }
            }
        }).start();
    }
}

 

请用“等待唤醒”机制编写一个程序,要求:
第一个线程:遍历1–1000所有的数字,在遍历过程中,如果发现这个数字能 同时被2,3,5,7整除,立即wait()退出等待,让第二个线程进入。
第二个线程:运行后,将一个计数器 + 1,之后再唤醒等待的线程。
主线程中:休息2秒,让两个线程全部执行完毕,打印“计数器”的结果。

public class Test {
    public static void main(String[] args) {
        Lock lock = new Lock();
        //创建线程
        Thread1 thread1 = new Thread1(lock);
        thread1.start();

        Thread2 thread2 = new Thread2(lock);
        thread2.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("计数器结果是:"+thread2.count);

    }
}
class Lock{
    //判断是否需要被唤醒
    boolean needNofity = false;

}
class Thread1 extends Thread {
    private Lock lock;

    public Thread1(Lock lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock){
            for (int i = 1; i < 1001; i++) {
                if(i % 2 == 0 && i % 3 == 0 && i % 5 == 0 && i % 7 ==0){
                    try {
                        System.out.println(i+"==>进入等待");
                        //告诉另一个线程需要被唤醒,唤醒一次就+1一次
                        lock.needNofity = true;
                        //自己的线程等待
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //唤醒另外一个线程
                lock.notify();
            }

        }
    }
}
class Thread2 extends Thread{
    private Lock lock;

    public Thread2(Lock lock) {
        this.lock = lock;
    }
    public int count = 0;
    @Override
    public void run() {
        //定义while循环、如果是true就循环
        while(true) {
            synchronized (lock) {
                //判断是否需要被唤醒
                if (lock.needNofity) {
                    //唤醒
                    lock.notify();
                    //唤醒一次就+1
                    System.out.println("唤醒:" + (++count) + "");
                    //再把状态变成false,继续循环
                    lock.needNofity = false;
                }
                try {
                    //自己等待
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 

 

 

  

 

posted @ 2022-07-08 09:39  zj勇敢飞,xx永相随  阅读(98)  评论(0编辑  收藏  举报