java多线程(三):wait()、sleep()、 join()和yield()区别

末鹿安然 提交于 2020-02-25 00:32:29

前言

首先需要先了解synchronized具体的使用方法

接着认识两个概念:
1.锁池

所有需要竞争同步锁的线程都会放在锁池当中,如果当前对象的锁已经被其中一个线程得到,则其他线程需要在这个锁池进行等待,当之前的线程释放同步锁后,锁池中的所有线程都会去竞争同步锁,当某个线程得到后会进入就绪队列进行等待cpu资源分配。

2.等待池

当我们调用wait()方法后,线程会放到等待池当中,等待池的线程是不会去竞争同步锁。只有调用了notify()或notifyAll()后等待池的线程才会开始去竞争锁,notify()是随机从等待池选出一个线程放到锁池,而notifyAll()是将等待池的所有线程放到锁池当中

区别

1.sleep()方法

在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。sleep()使当前线程进入阻塞状态,在指定时间内不会执行。sleep()会指定休眠时间,线程休眠的时候会大于或者等于该休眠时间,当时间过后该线程会由“阻塞状态”编程“就绪状态”。
注意:sleep方法只是让出了cpu的执行权,并不会释放同步资源锁。

2.yield()方法

yield()方法和sleep()方法类似,也不会释放“锁标志”,区别在于,它没有参数,yield()的作用是让步,它能够让当前线程从“运行状态”进入到“就绪状态”,从而让其他等待线程获取执行权,但是不能保证在当前线程调用yield()之后,其他线程就一定能获得执行权,也有可能是当前线程又回到“运行状态”继续运行。

3.join()方法

join()方法会使当前调用的线程等待调用join()方法的线程结束后才能继续执行,例如当前进行的进行的线程是a,在调用b.join()方法后,a线程会等待b线程执行完毕或中断线程后a才会继续执行。

public class TestJoin {

    public static void main(String[] args) {
        Thread thread = new Thread(new JoinDemo());
        thread.start();

        for (int i = 0; i < 20; i++) {
            System.out.println("主线程第" + i + "次执行!");
            if (i >= 2)
                try {
                    // t1线程合并到主线程中,主线程停止执行过程,转而执行t1线程,直到t1执行完毕后继续。
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        }
    }
}

class JoinDemo implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("线程1第" + i + "次执行!");
        }
    }
}

结果如下
在这里插入图片描述

4.wait()方法

  • wait()必须在synchronized 修饰的同步代码块中调用
  • wait()会释放cpu资源和释放同步锁(类锁和对象锁)
  • 调用wait()后必须调用notify()或notifyAll()后线程才会从等待池进入到锁池,当我们的线程竞争得到同步锁后就会重新进入绪状态等待cpu资源分配
  • wait()是Object类的方法

Object.wait()和Thread.sleep()都可以让程序等待若干时间,区别在于sleep()方法不会释放对象锁,而wait会释放锁

public class Demo{
    final static Object person =new Object();
    public static class T1 extends Thread{
        public void run(){
            synchronized (person){
                System.out.println(System.currentTimeMillis()+"T1 come");
                try{
                    System.out.println(System.currentTimeMillis()+"T1 wait");
                    person.wait();
                }catch (InterruptedException r){
                    r.getStackTrace();
                }
                System.out.println(System.currentTimeMillis()+"T1 over");
            }
        }
    }
    public static class T2 extends Thread{
        public void run(){
            synchronized (person){
                System.out.println(System.currentTimeMillis()+"T2 come");
                person.notify();
                System.out.println(System.currentTimeMillis()+"T2 over");
                try{
                    Thread.sleep(2000);
                }catch (InterruptedException r){
                    r.getStackTrace();
                }
 
            }
        }
    }
 
    public static void main(String args[]){
        try{
            Thread thread1=new T1();
            Thread thread2=new T2();
            thread1.start();
            thread2.start();
        }catch (Exception e){
            e.printStackTrace();
        }
 
    }
}

结果如下
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!