`
HelloSure
  • 浏览: 308350 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

多线程例子:wait与notify、sleep

 
阅读更多
package sure;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class Test {

	private static Logger log = LoggerFactory.getLogger(Test.class);
	
    public static void main(String[] args) throws Exception {  
        final Object lock="";  
        Thread t1=new Thread(){  
            public void run(){  
                try {  
                	log.info("t1 wait begin");  
                    synchronized (lock) {  
                    	log.info("t1 get lock, wait begin");
                        lock.wait();  
                        log.info("t1 wait end,release lock");
                        lock.notifyAll();
                    }  
                    log.info("t1  wait end");  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  
        };  
          
        t1.start();  
        log.info("t1 start and sleep");
        for(int i=0;i<10000001;i++){
        	if(i==10000000)
        		log.info("i end");
        }
        Thread.sleep(5000);  
        log.info("sleep(5000) end");
          
        log.info("main lock begin");  
        synchronized (lock) {
        	log.info("main get lock");
            lock.notify();
            log.info("notify");
            Thread.sleep(10000); 
            log.info("sleep 10000 end");
            log.info("main wait begin ");  
            lock.wait();  
            log.info("main wait end");  
        }  
        log.info("main lock end");  
    }  
}



日志信息如下:
2011-11-09 15:44:05,968 INFO [sure.Test] - t1 start and sleep
2011-11-09 15:44:05,968 INFO [sure.Test] - t1 wait begin
2011-11-09 15:44:05,968 INFO [sure.Test] - t1 get lock, wait begin
2011-11-09 15:44:05,984 INFO [sure.Test] - i end
2011-11-09 15:44:10,984 INFO [sure.Test] - sleep(5000) end
2011-11-09 15:44:10,984 INFO [sure.Test] - main lock begin
2011-11-09 15:44:10,984 INFO [sure.Test] - main get lock
2011-11-09 15:44:10,984 INFO [sure.Test] - notify
2011-11-09 15:44:20,984 INFO [sure.Test] - sleep 10000 end
2011-11-09 15:44:20,984 INFO [sure.Test] - main wait begin 
2011-11-09 15:44:20,984 INFO [sure.Test] - t1 wait end,release lock
2011-11-09 15:44:20,984 INFO [sure.Test] - t1  wait end
2011-11-09 15:44:20,984 INFO [sure.Test] - main wait end
2011-11-09 15:44:20,984 INFO [sure.Test] - main lock end


wait,notify,notifyAll必须在当前线程获得监视器时才能调用,即这些方法必须在同步块中才能调用。

被阻塞的线程在被notify之后,并不是马上可以执行,而是“可执行”,要到获得锁之后才能真正开始执行。

从这个例子进行各种修改可以用来加深对线程的理解。
package sure;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class Test {

	private static Logger log = LoggerFactory.getLogger(Test.class);
	
    public static void main(String[] args) throws Exception {  
        final Object lock="";  
        Thread t1=new Thread(){  
            public void run(){  
                try {  
                	log.info("t1 wait begin");  
                    synchronized (lock) {  
                    	log.info("t1 get lock, wait begin");
                    	Thread.sleep(5000);
                    	log.info("sleep end");
                        lock.wait();  
                        log.info("t1 wait end,release lock");
                        lock.notifyAll();
                    }  
                    Thread.sleep(5000);
                    log.info("t1  wait end");  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  
        };  
          
        t1.start();  
        log.info("t1 start and sleep");
          
        log.info("main lock begin");  
        synchronized (lock) {
        	log.info("main get lock");
            lock.notify();
            log.info("notify");
            Thread.sleep(10000); 
            log.info("sleep 10000 end");
            log.info("main wait begin ");  
            lock.wait();  
            log.info("main wait end");  
        }  
        log.info("main lock end");  
       
    }  

}

日志为:
2011-11-09 16:55:19,031 INFO [sure.Test] - t1 start and sleep
2011-11-09 16:55:19,031 INFO [sure.Test] - main lock begin
2011-11-09 16:55:19,031 INFO [sure.Test] - main get lock
2011-11-09 16:55:19,031 INFO [sure.Test] - notify
2011-11-09 16:55:19,031 INFO [sure.Test] - t1 wait begin
2011-11-09 16:55:29,031 INFO [sure.Test] - sleep 10000 end
2011-11-09 16:55:29,031 INFO [sure.Test] - main wait begin 
2011-11-09 16:55:29,031 INFO [sure.Test] - t1 get lock, wait begin
2011-11-09 16:55:34,031 INFO [sure.Test] - sleep end

然后两个线程都会被阻塞,造成死锁。
这个例子进一步说明了同步的用法,另外也表明了Thread.sleep是针对当前运行线程的。

有趣的是,同样是这个代码,在另一种情况下会出现这种情况:
2011-11-09 22:06:05,930 INFO [sure.Test] - t1 start and sleep
2011-11-09 22:06:05,930 INFO [sure.Test] - t1 wait begin
2011-11-09 22:06:05,930 INFO [sure.Test] - main lock begin
2011-11-09 22:06:05,930 INFO [sure.Test] - t1 get lock, wait begin
2011-11-09 22:06:10,930 INFO [sure.Test] - sleep end
2011-11-09 22:06:10,930 INFO [sure.Test] - main get lock
2011-11-09 22:06:10,930 INFO [sure.Test] - notify
2011-11-09 22:06:20,930 INFO [sure.Test] - sleep 10000 end
2011-11-09 22:06:20,930 INFO [sure.Test] - main wait begin 
2011-11-09 22:06:20,930 INFO [sure.Test] - t1 wait end,release lock
2011-11-09 22:06:20,930 INFO [sure.Test] - main wait end
2011-11-09 22:06:20,930 INFO [sure.Test] - main lock end
2011-11-09 22:06:25,930 INFO [sure.Test] - t1  wait end

这种情况不会造成死锁阻塞。
由于这两个线程都谁都可能先进入同步块中,所以就造成了两个截然不同的情况。但是上面第一种情况就肯定是子进程先进入同步块,因为main进程用sleep拖延了。
分享到:
评论

相关推荐

    深入理解Wait、Notify和Wait与sleep区别

    3(深入理解Wait、Notify和Wait与sleep区别).rar

    java多线程设计模式

    java多线程设计模式 线程的创建和重起 线程的同步 wait/notify/sleep机制 Worker Pattern

    java 多线程设计模式 进程详解

    《JAVA多线程设计模式》PDF 下载 《Java线程 高清晰中文第二版》中文第二版(PDF) 前言 第一章 线程简介 Java术语 线程概述 为什么要使用线程? 总结 第二章 Java线程API 通过Thread类创建线程 使用Runable接口...

    这就是标题—— JUC.pdf

    多线程锁 并发下的集合类 List Set Map Callable接口 线程创建的方式 callable / runnable FutureTask JUC常用辅助类 CountDownLatch (减少计数器) CyclicBarrier(加法计数器) Semaphore(信号量,流量控制) ...

    JAVA多线程技术分享-39页PPT(winding)

    分享的多线程技术不是告诉你什么是线程,线程的状态,而是我们在开发中容易踩的坑,受过的伤害。我不会告诉你什么是爱情,但是我会告诉你爱过。 一 基础: 1,Thread.sleep(0)的作用 2,为什么线程会带来性能问题 3...

    多线程,高并发.zip

    1. stop() 和 suspend() 方法为何不推荐使用? 反对使用 stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且...若标志指出线程应当恢复,则用一个 notify() 重新启动线程。 2. sleep() 和 wait() 有什么区别?

    java笔试题大集合及答案(另附各大公司笔试题)

    60、java中有几种方法可以实现一...答:多线程有两种实现方法,分别是继承Thread类与实现Runnable接口 同步的实现方面有两种,分别是synchronized,wait与notify 67、线程的基本概念、线程的基本状态以及状态之间的关系

    LeetCode判断字符串是否循环-java:Java

    LeetCode判断字符串是否循环 知识点总结 java基础 1、使用迭代器和for each循环查看集合元素时只能获得元素的值,不能改变元素 ...object的方法:wait(notify,notifyall),thread的方法:(sleep、join),结束

    jstack生成的Thread Dump日志.docx

    临界区的设置是为了保证其内部的代码执行的原子性和完整性,但因为临界区在任何时间只允许线程串行通过,这和我们使用多线程的初衷是相反的。如果在多线程程序中大量使用synchronized,或者不适当的使用它,会造成...

    汪文君高并发编程实战视频资源全集

    │ 高并发编程第二阶段04讲、多线程的休息室WaitSet详细介绍与知识点总结.mp4 │ 高并发编程第二阶段05讲、一个解释volatile关键字作用最好的例子.mp4 │ 高并发编程第二阶段06讲、Java内存模型以及CPU缓存不一致...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第二阶段04讲、多线程的休息室WaitSet详细介绍与知识点总结.mp4 │ 高并发编程第二阶段05讲、一个解释volatile关键字作用最好的例子.mp4 │ 高并发编程第二阶段06讲、Java内存模型以及CPU缓存不一致...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【多线程】sleep()和wait()分别是哪个类的方法,有什么区别? 79 【多线程】sleep()和yield()的区别 79 【多线程】对synchronized理解?用在代码块和方法上有什么区别? 80 【多线程】Volatile的理解 82 【*多线程】...

    javo::rocket: 任何 Java 开发人员都能负担得起的沙盒虚拟机

    贾沃 注意:(以前称为Jago ) 用 Go 语言编写的简化 Java 虚拟机。 一个目标是深入学习 JVM 规范,并尝试了解 Java ... 监控、 sleep 、 wait 、 notify支持 JDK 本地方法 GC 准时制 怎么跑 构建和安装 ❯ cd ~

    进销存系统文档作业例子

    与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...

    java面试题

    答:Servlet与CGI的区别在于Servlet处于服务器进程中,它通过多线程方式允许其service方法,一个实例可以服务于多个请求,并且其实例一般不会被销毁,而CGI对每个请求都产生新的进程,服务完后就销毁,所以效率上...

    Java语言程序设计(一)真题及答案.doc

    A.sleep() B.notify() C.wait() D.join() 正确答案:B 您的答案: 本题解析: 暂无解析 2.以下标识符中,不是Java语言关键字的是()。 A.wait B.new C.long D.switch 正确答案:A 您的答案: 本题解析: 暂无解析 3....

    超级有影响力霸气的Java面试题大全文档

    与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...

    java 面试题 总结

    与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...

    线程间通信

    //当bFull为 true ,Consumer线程才能取走数据,取走数据后bFull置为 false //当bFull为 false,Procucer线程才能写入数据,写入数据后bFull置为 true boolean bFull=false; public synchronized ...

    Java高级程序设计测试含答案.docx

    update() 在线程同步中,为了唤醒另一个等待的线程,使用下列方法 () [单选题] * A.sleep() B.wait() C.notify()(正确答案) D. join() Java高级程序设计测试含答案全文共40页,当前为第4页。Java提供以下哪个...

Global site tag (gtag.js) - Google Analytics