对象中的等待集(wait,notify,notifyAll)

wait():

1.wait()会使线程状态发生变化(runnable-->waiting,waiting-->runnable)

2.等的是对像的等待集上(wait()是Object的一个方法,所以等在该对象的等待集上)

3.使用的时候必须加锁,等在哪个对象上,就对哪个对象加锁(wait()执行成功时会释放锁,醒来时会重新请求锁)

4.哪个线程调用wait(),哪个线程进入等待集

5.notify()只唤醒一个,但不保证是哪一个,但notifyAll()会唤醒所有对象

public class WaitDemo {
    private static Object object=new Object();
    public static class A extends Thread{
        @Override
        public void run() {
            for(int i=0;i<10;i++){
                System.out.println(i);
            }

            synchronized (object){
                try {
                    //1.释放object中的锁
                    //2.把线程放到object对象的等待集中
                    //3.把线程状态变为waiting
                    //wait()执行后,锁会被释放
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for(int i=100;i<110;i++)
            {
                System.out.println(i);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread a=new A();
        a.start();
        Scanner scanner=new Scanner(System.in);
        scanner.nextLine();
        //被唤醒后
        //1.把A线程从等待集中取出
        //2.把A线程变的状态变为runnable
        //3.尝试重新抢object的锁
        synchronized (object){
            object.notify();
        }
        System.out.println("main已执行完毕");
    }
}

示例:有两个线程,n的范围只能是【0,10】,一个线程负责n++,一个线程负责n--

public class Nwait {
    private static Object o=new Object();
    private static int n=0;
    private static class Sub extends Thread{
        @Override
        public void run() {
            while(true){
                synchronized (o){
                    if(n==0){
                        try {
                            o.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    //因为没把锁释放,所以把notify()放到这里也是可以的
                    //o.notify();
                    n--;
                    System.out.println(getName()+":"+n);
                    o.notify();
                }
            }
        }
    }
    private static class Add extends Thread{
        @Override
        public void run() {
            while(true){
                synchronized (o){
                    if(n==9){
                        try {
                            o.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    n++;
                    System.out.println(getName()+":"+n);
                    o.notify();
                }
            }
        }
    }

    public static void main(String[] args) {
        Thread sub=new Sub();
        Thread add=new Add();
        sub.start();
        add.start();
    }
}

力扣1114(按序打印):

public class OneTwoThree {
    private static class Foo {
        private volatile int n = 0;

        //当n不为0时,不释放CPU,导致n无法及时更新
        public void oneVersion1() {
            synchronized (this) {
                if (n != 0) {
                    return;
                }
                System.out.println("one");
                n = 1;
            }
        }

        //减少了锁的开销
        public void oneVersion2() {
            if (n != 0) {
                return;
            }
            System.out.println("one");
            n = 1;
        }

        //当n不为0时,线程会释放CPU,但是该线程任然参与CPU的抢夺
        public void oneVersion3() {
            if (n != 0) {
                //通过yield释放CPU,可以适当增加性能
                Thread.yield();
                return;
            }
            //两句话次序不能颠倒
            System.out.println("one");
            n = 1;
        }
        //当n不为0时,线程不在参与CPU的抢夺,提高了代码的速度
        public void oneVersion4() throws InterruptedException {
            if (n != 0) {
                synchronized (this) {
                    this.wait();
                }
            }
            //两句话顺序不能颠倒
            // 极端情况下,n=1执行后,线程调度,
            // 会导致n的值改变却没有打印“one”,下次直接打印“two”
            System.out.println("one");
            n = 1;
            synchronized (this) {
                this.notifyAll();
            }
        }
    }
}

死锁:

当A线程获得了lockA,这时时间片到了,A线程被调度出去了,B线程进来了,B线程获得了lockB,等下次时间到了,不管A线程还是B线程都不可能获得另外一把锁,彼此都锁住了对方线程,这就叫死锁

sleep()与wait()的区别:

1.wait()之前需要请求锁,执行时会释放锁,等被唤醒时在重新请求锁。这个锁是wait对像上的monitor lock

2.sleep()是无视锁的存在,即之前请求的锁不会被释放,没有锁也不会请求

3.wait()是Object的普通方法

4.sleep()是Thread的静态方法

消费者生产者问题:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值