JAVA线程sleep()和wait()详解及实例

 更新时间:2017年05月12日 09:48:01   投稿:lqh  
这篇文章主要介绍了JAVA线程sleep()和wait()详解及实例的相关资料,探讨一下sleep()和wait()方法的区别和实现机制,需要的朋友可以参考下

JAVA线程sleep()和wait()详解及实例

sleep

1.sleep是Thread的一个静态(static)方法。使得Runnable实现的线程也可以使用sleep方法。而且避免了线程之前相互调用sleep()方法,引发死锁。

2.sleep()执行时需要赋予一个沉睡时间。在沉睡期间(阻塞线程期间),CPU会放弃这个线程,执行其他任务。当沉睡时间到了之后,该线程会自动苏醒,不过此时线程不会立刻被执行,而是要等CPU分配资源,和其他线程进行竞争。

3.此外如果这个线程之前获取了一个机锁,在沉睡期间,这个机锁不会释放。其他等待这个机锁的程序,必须等待这个线程醒来,且执行完后才能运行。

sleep相关代码

public class ThreadTest2 {

  public static void main(String[] args){
    System.out.println("begin our test");
    ThreadSleep sleep = new ThreadSleep();
    try {
      Thread thread1 = new Thread(sleep,"路人甲");
      Thread thread2 = new Thread(sleep,"路人乙");
      thread1.start();
      thread2.start();
    }catch(Exception e){
      e.printStackTrace();
    }
    System.out.println("test is over");
  }


}

 class ThreadSleep implements Runnable{

   int count = 0;

   @Override
   public void run(){
     System.out.println(Thread.currentThread().getName() + " say : hello sleep !!");
     count();

   }

   public void count(){
     while(count < 20) {
         System.out.println(Thread.currentThread().getName() + " say : count is " + count);
         try {
           count++;
           Thread.sleep(100);
         } catch (Exception e) {
           e.printStackTrace();
         }
     }

   }
}

输出日志

begin our test
test is over
路人甲 say : hello sleep !!
路人甲 say : count is 0
路人乙 say : hello sleep !!
路人乙 say : count is 1
路人甲 say : count is 2
路人乙 say : count is 2
路人甲 say : count is 4
路人乙 say : count is 4
路人甲 say : count is 6
路人乙 say : count is 7
路人乙 say : count is 8
路人甲 say : count is 8
路人甲 say : count is 10
路人乙 say : count is 10
路人乙 say : count is 12
路人甲 say : count is 12
路人乙 say : count is 14
路人甲 say : count is 14
路人甲 say : count is 16
路人乙 say : count is 16
路人甲 say : count is 18
路人乙 say : count is 18

通过日志可以发现线程甲和线程乙基本是交替执行,但是并不规律,且出现了并发问题。

该情况是由于代码中设置了睡眠时间为100毫秒,由于count递增执行速度很快,所以线程差不多是同时睡眠,然后同时苏醒并导致了并发的出现。

接下来要添加synchronize块,检查sleep时机锁是否释放

public class ThreadTest2 {

  public static void main(String[] args){
    System.out.println("begin our test");
    ThreadSleep sleep = new ThreadSleep();
    try {
      Thread thread1 = new Thread(sleep,"路人甲");
      Thread thread2 = new Thread(sleep,"路人乙");
      thread1.start();
      thread2.start();
    }catch(Exception e){
      e.printStackTrace();
    }
    System.out.println("test is over");
  }


}

class ThreadSleep implements Runnable{

  int count = 0;

  @Override
  public void run(){
    System.out.println(Thread.currentThread().getName() + " say : hello sleep !!");
    count();

  }

  public void count(){
    while(count < 20) {
      synchronized (this) {
        System.out.println(Thread.currentThread().getName() + " say : count is " + count);
        try {
          count++;
          Thread.sleep(100);
        } catch (Exception e) {
          e.printStackTrace();
        }

      }
    }

  }
}

输出日志

begin our test
路人甲 say : hello sleep !!
路人甲 say : count is 0
test is over
路人乙 say : hello sleep !!
路人甲 say : count is 1
路人甲 say : count is 2
路人甲 say : count is 3
路人甲 say : count is 4
路人甲 say : count is 5
路人甲 say : count is 6
路人甲 say : count is 7
路人甲 say : count is 8
路人甲 say : count is 9
路人甲 say : count is 10
路人甲 say : count is 11
路人甲 say : count is 12
路人甲 say : count is 13
路人甲 say : count is 14
路人甲 say : count is 15
路人甲 say : count is 16
路人甲 say : count is 17
路人甲 say : count is 18
路人甲 say : count is 19
路人乙 say : count is 20

通过日志可以看出,基本是线程甲在执行,这是因为sleep时,机锁一直在线程甲上,所以线程乙只能一直等待直到线程甲释放锁。

wait

1.wait()是Object类的一个方法。当调用wait()方法时,该线程会进入和该对象相关的等待池中,并释放它所拥有的机锁。

2.执行wait()后,必须使用notify()方法或notifyAll()方法或设置等待时间(wait(long time))唤醒在等待线程池中的线程。

3.wait()必须放在synchronized block中,否则会在运行时报“java.lang.IllegalMonitorStateException”异常

wait相关代码

public class ThreadTest2 {

  public static void main(String[] args) {
    System.out.println("begin our test");
    ThreadSleep sleep = new ThreadSleep();
    try {
      Thread thread1 = new Thread(sleep, "路人甲");
      Thread thread2 = new Thread(sleep, "路人乙");
      thread1.start();
      thread2.start();
    } catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println("test is over");
  }
}

class ThreadSleep implements Runnable {

  int count = 0;

  @Override
  public void run() {
    System.out.println(Thread.currentThread().getName() + " say : hello sleep !!");
    count();

  }

  public void count() {
    while (count < 20) {
      synchronized (this) {
        System.out.println(Thread.currentThread().getName() + " say : count is " + count);
        try {
          count++;
          this.wait(100);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }

  }
}

输出日志

begin our test
路人甲 say : hello sleep !!
路人甲 say : count is 0
test is over
路人乙 say : hello sleep !!
路人乙 say : count is 1
路人甲 say : count is 2
路人乙 say : count is 3
路人甲 say : count is 4
路人乙 say : count is 5
路人甲 say : count is 6
路人乙 say : count is 7
路人甲 say : count is 8
路人乙 say : count is 9
路人甲 say : count is 10
路人乙 say : count is 11
路人甲 say : count is 12
路人乙 say : count is 13
路人乙 say : count is 14
路人甲 say : count is 15
路人乙 say : count is 16
路人甲 say : count is 17
路人乙 say : count is 18
路人甲 say : count is 19

通过日志可以发现在wait的情况下,机锁会被释放。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

相关文章

  • SpringMVC实现Validation校验过程详解

    SpringMVC实现Validation校验过程详解

    这篇文章主要介绍了SpringMVC实现Validation校验过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • JVM的类加载器和双亲委派模式你了解吗

    JVM的类加载器和双亲委派模式你了解吗

    这篇文章主要为大家详细介绍了JVM类加载器和双亲委派模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • 新手入门Jvm--jvm概览

    新手入门Jvm--jvm概览

    JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的
    2021-06-06
  • Java实现权重随机获取值或对象的方法

    Java实现权重随机获取值或对象的方法

    这篇文章主要介绍了Java实现权重随机获取值或对象的方法,treeMap是一种基于红黑树实现的有序映射表,提供了一系列的方法来操作映射表中的元素,其中tailMap方法是用于返回映射表中大于或等于给定键的部分视图,需要的朋友可以参考下
    2023-11-11
  • 详解java中DelayQueue的使用

    详解java中DelayQueue的使用

    这篇文章主要介绍了java中DelayQueue的使用,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-10-10
  • AsyncHttpClient exception异常源码流程解析

    AsyncHttpClient exception异常源码流程解析

    这篇文章主要为大家介绍了AsyncHttpClient的exception源码流程解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • java基础之NIO介绍及使用

    java基础之NIO介绍及使用

    这篇文章主要介绍了java基础之NIO介绍及使用,文中有非常详细的代码示例,对正在学习java基础的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • 浅谈一下Java为什么不能使用字符流读取非文本的二进制文件

    浅谈一下Java为什么不能使用字符流读取非文本的二进制文件

    这篇文章主要介绍了浅谈一下为什么不能使用字符流读取非文本的二进制文件,刚学Java的IO流部分时,书上说只能使用字节流去读取图片、视频等非文本二进制文件,不能使用字符流,否则文件会损坏,需要的朋友可以参考下
    2023-04-04
  • 养成良好java代码编码规范

    养成良好java代码编码规范

    这篇文章主要介绍了如何养成良好java代码编码规范,规范需要平时编码过程中注意,是一个慢慢养成的好习惯,下面小编就带大家来一起详细了解一下吧
    2019-06-06
  • SpringSecurity微服务实战之公共模块详解

    SpringSecurity微服务实战之公共模块详解

    这篇文章主要为大家介绍了SpringSecurity微服务实战之公共模块详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08

最新评论