多线程方法学习

博客贡献阅读:

1:多线程的学习:https://blog.csdn.net/xingjing1226/article/details/81977129

2:对象锁释放:https://www.jianshu.com/p/ffc0c755fd8d,关于notify以及wait是否释放锁的问题

3:锁对象和wait()方法不一致导致的问题:https://blog.csdn.net/fangaiming1/article/details/107532472

1、yield的使用

线程调用yield会让线程进入就绪状态,重新争夺资源,有可能会被其他线程获取,也有可能还是自己获取到线程资源

public static void main(String[] args) {
        Thread oneThread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=1;i<10;i++){
                    if (i == 5){
                        Thread.yield();
                    }
                    System.out.println(Thread.currentThread().getName()+"i=="+i);
                }
            }
        },"one");


        Thread twoThread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=1;i<10;i++){
                    System.out.println(Thread.currentThread().getName()+"i=="+i);
                }
            }
        },"two");

        oneThread.start();

        twoThread.start();

    }
View Code

如上:线程one可能还会重新获取到资源,也有可能被线程two获取到资源,主要看他们之间的相互竞争

 

2、sleep()的使用,同join一样

线程调用sleep方法,会让线程处于等待状态,等到等待事件过后,重新进入就绪状态,等待获取资源执行

 

3、wait()/notify方法的使用

注意:wait方法必须配合synchronized一起使用,因为涉及到线程之间的通信,必须得有一个锁机型控制,阻塞某个线程,不然

就会出现时间片轮询得操作了,就不会有线程之间的通信了,可以看上面博客,线程锁释放

错误示范:

public class ShoesTest {

    public static void main(String[] args) {
        Shoes shoes = new Shoes();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Shoes.class) {
                    while (true) {
                        if (shoes.getNum() == 0) {
                            try {
                                System.out.println("进入等待程序");
                                shoes.wait();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        shoes.subNum();
                        System.out.println("消费一双鞋");
                        //shoes.notify();

                    }
                }
            }
        }).start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Shoes.class) {
                    while (true) {
                        if (shoes.getNum() > 0) {
                            try {
                                shoes.notify();
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }

                        shoes.addNum();
                        System.out.println("生产一双鞋");
                        //shoes.notify();

                    }
                }
            }
        }).start();
    }
}
View Code

上面存在两个问题:

第一:锁对象是Class而非对象,这回引发异常问题,导致wait不进入阻带,可以惨遭2,和3这两篇博客看

第二:notify并不会立马释放锁,会等代码块执行完成以后才会释放锁的,所以当锁对象换成shoes的时候,会一直执行第二个线程

无法从while(true)中醒过来

正确的实列:

public class ShoesTest {

    public static void main(String[] args) {
        Shoes shoes = new Shoes();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Shoes.class) {
                    while (true) {
                        if (shoes.getNum() == 0) {
                            try {
                                System.out.println("进入等待程序");
                                shoes.wait();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        shoes.subNum();
                        System.out.println("消费一双鞋");
                        shoes.notify();

                    }
                }
            }
        }).start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Shoes.class) {
                    while (true) {
                        if (shoes.getNum() > 0) {
                            try {
                                shoes.wait();
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }

                        shoes.addNum();
                        System.out.println("生产一双鞋");
                        shoes.notify();
                    }
                }
            }
        }).start();
    }
}
View Code

保证使用wait释放当前锁,退出while(true)循环

一张图来总结线程的流转状态:

 

posted @ 2022-07-01 11:18  xzlnuli  阅读(16)  评论(0编辑  收藏  举报