Java多线程--wait和join
2015-07-08 23:45
453 查看
首先从公司一道笔试题开始
问23行代码怎么写,才能让24行打印出10?
不少笔试者会选t.wait()或者th.wait()!
面试的时候问他为什么,他具体也说不清楚,感觉就是见过这个wait方法,但是wait方法的含义确一知半解。
wait 是什么意思呢?我举例子啊,比如我想让本线程放弃当前对象锁,说直白点就是让别的对象进入同步块
如上例,你会看到输出
Thread-0enter
Thread-1enter
不会看到
Thread-1out
Thread-0out
因为Thread-0 先获得了Object i 锁,然后运行到13行,释放了该锁,
这个时候Thread-1就获得了Object i 锁,进入了同步代码块,然后同样运行13行,也释放了该锁。
这个时候在有两个线程Thread-0和Thread-1等待获得Object i 锁,由于代码中没有调用i.notifyAll(),所以这个程序永远不会退出。
但是如果打开注释11行,那么你将会看到结果
Thread-0enter
Thread-1enter
Thread-0out
因为Thread-0 先获得了Object i 锁,然后运行到13行,释放了该锁,
这个时候Thread-1就获得了Object i 锁,进入了同步代码块,运行到11行,i.notify(),
那么这个意思就是说别的等待i锁的线程可以唤醒了,一旦我(Thread-1)释放锁(13行调用wait()),那么Thread-0就可以获得i锁继续执行了。
此程序中没有在Thread-1 释放i锁(wait())之后notify,所以永远不会看到Thread-1out
再回到这个题目,我们的意思是让主线程等待所有子线程执行完毕 ,再执行。更何况笔试题中没有锁对象。更别提wait()了。
所以,此处应该用th.join(); Thread.join()方法会阻塞主线程继续向下执行。
package test; public class Test implements Runnable { public int i = 0; @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } i = 10; } public static void main(String[] args) { try { Test t = new Test(); Thread th = new Thread(t); th.start(); th.join(); System.out.println(t.i); } catch (Exception ex) { } } }
问23行代码怎么写,才能让24行打印出10?
不少笔试者会选t.wait()或者th.wait()!
面试的时候问他为什么,他具体也说不清楚,感觉就是见过这个wait方法,但是wait方法的含义确一知半解。
wait 是什么意思呢?我举例子啊,比如我想让本线程放弃当前对象锁,说直白点就是让别的对象进入同步块
package test; public class Test implements Runnable { public Object i = new Object(); @Override public void run() { synchronized (i) { System.out.println(Thread.currentThread().getName()+"enter "); // i.notify(); try { i.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"out "); } } public static void main(String[] args) { try { Test t = new Test(); Thread th1 = new Thread(t); Thread th2 = new Thread(t); th1.start(); th2.start(); } catch (Exception ex) { } } }
如上例,你会看到输出
Thread-0enter
Thread-1enter
不会看到
Thread-1out
Thread-0out
因为Thread-0 先获得了Object i 锁,然后运行到13行,释放了该锁,
这个时候Thread-1就获得了Object i 锁,进入了同步代码块,然后同样运行13行,也释放了该锁。
这个时候在有两个线程Thread-0和Thread-1等待获得Object i 锁,由于代码中没有调用i.notifyAll(),所以这个程序永远不会退出。
但是如果打开注释11行,那么你将会看到结果
Thread-0enter
Thread-1enter
Thread-0out
因为Thread-0 先获得了Object i 锁,然后运行到13行,释放了该锁,
这个时候Thread-1就获得了Object i 锁,进入了同步代码块,运行到11行,i.notify(),
那么这个意思就是说别的等待i锁的线程可以唤醒了,一旦我(Thread-1)释放锁(13行调用wait()),那么Thread-0就可以获得i锁继续执行了。
此程序中没有在Thread-1 释放i锁(wait())之后notify,所以永远不会看到Thread-1out
再回到这个题目,我们的意思是让主线程等待所有子线程执行完毕 ,再执行。更何况笔试题中没有锁对象。更别提wait()了。
所以,此处应该用th.join(); Thread.join()方法会阻塞主线程继续向下执行。
public class TestThread extends Thread { private CountDownLatch countDownLatch; public TestThread(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } public void run() { System.out.println(this.getName() + "子线程开始"); try { // 子线程休眠五秒 Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.getName() + "子线程结束"); // 倒数器减1 countDownLatch.countDown(); } }
public class Main { public static void main(String[] args) { long start = System.currentTimeMillis(); // 创建一个初始值为5的倒数计数器 CountDownLatch countDownLatch = new CountDownLatch(5); for(int i = 0; i < 5; i++) { Thread thread = new TestThread(countDownLatch); thread.start(); } try { // 阻塞当前线程,直到倒数计数器倒数到0 countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("子线程执行时长:" + (end - start)); } }
相关文章推荐
- java实现批量下载百度图片搜索到的图片
- java进阶 ------ Java NIO
- 【转】如何修改maven工程jdk版本
- 在mac下搭建java开发环境
- 触摸java常量池
- UTF-8编码规则(摘自JDK官方文档)
- Java基础 泛型基础
- Java Scanner next()和nextLine()的区别
- java版排序算法简介及冒泡排序以及优化,选择排序,直接插入排序,希尔排序,堆排序,快速排序及其优化前言 2 分类 2 稳定性 3 时间复杂度 4 Java实现版本 5 1、冒泡排序 6 2、选择排序
- 用JAXB转换XML和Java对象时的循环引用问题的解决方法
- Java Class 是什么
- Java NIO 系列教程
- JAVA设计模式之代理模式
- Java引用数据类型的声明与创建
- json、javaBean、xml互转的几种工具介绍
- java跳出多重嵌套循环
- Java学习笔记--入门案例
- Java注解 (Annotation)自定义注解入门
- Eclipse环境下 使用Gradle进行编译实现自动分包
- 浅谈Java多线程