Java多线程--wait和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多线程--wait和join的更多相关文章
- java多线程wait notify join
wait notify 几个注意点: wait 与 notify/notifyAll 方法必须在同步代码块中使用,即要先对调用对象加锁. 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进 ...
- java 多线程8(join)
join(): 加入.一个线程如果执行了join语句,那么就有新的线程加入,执行该语ij 句的线程必须要让步给新加入的线程先完成任务,然后才能继续执行. import java.util.Scann ...
- Java多线程中的join()方法
一.join()方法介绍 join() 定义在Thread.java中.join()方法把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的join( ...
- 浅谈Java多线程中的join方法
先上代码 新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String ...
- Java多线程中的join方法
新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String name ...
- java多线程中关于join方法的使用
Thread的非静态方法join()让一个线程B"加入"到另外一个线程A的尾部.在A执行完毕之前,B不能工作.例如: Thread t = new MyThread ...
- thread.join函数,java多线程中的join函数解析
join函数的作用,是让当前线程等待,直到调用join()的 线程结束或者等到一段时间,我们来看以下代码 package mian; public class simpleplela { static ...
- Java多线程10:join()方法
一.前言 通过一个简单的例子引入join()方法 public class Thread01 extends Thread{ @Override public void run() { for(int ...
- java多线程16:join()的使用
讲解join()方法之前请确保对于即wait()/notify()/notifyAll()机制已熟练掌握.可以参考前面的笔记 join()方法的作用是等待线程销毁.join()方法反应的是一个很现实的 ...
随机推荐
- Android实现接口方式注册监听器
初学Android,新手大都倾向使用匿名类的方式注册监听器, 如下: public class MainActivity extends Activity { private Button but ...
- SuperSlide
今天又接触到另一个新的前端插件,心情美美哒~ SuperSlide 致力于解决网站大部分特效展示问题,使网站代码规范整洁,方便维护更新,官网地址:http://www.superslide2.com/ ...
- logcat的条数设置
在软件默认设置下,logcat的缓存为1024,即logcat显示的条数有限,给程序的调试带来很大的不便,通过设置 logcat缓存的大小,可以增加logcat显示的条数,将程序调试的输出都可以打印出 ...
- sphinx索引文件进一步说明——最好是结合lucene一起看,直觉告诉我二者本质无异
摘自:http://blog.csdn.net/cangyingzhijia/article/details/8592441 Sphinx使用的文件包括 "sph", " ...
- Windows Store App 全球化:在后台代码中引用字符串资源
上文提到了引用字符串资源具有两种方式,分别是在XAML元素中和在后台代码中引用资源文件中的字符串资源.在第一小节已经介绍了如何在XAML元素中引用字符串资源,本小节将讲解在后台代码中引用字符串资源的相 ...
- iOS开发多线程篇—NSOperation简单介绍
iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现 ...
- 苹果IOS系统SVN命令 同样适用于linux系统
1.将文件checkout到本地目录svn checkout path(path是服务器上的目录)例如:svn checkout svn://192.168.1.1/pro/domain简写:svn ...
- My Game --线段数据
在背景中用到了一个自定义的类 VectArr : class VectArr { public: VectArr( const Bezier & bz, int conut = 30 ) : ...
- eval解析非标准json
以前一直在用,但是不知道原理,惭愧啊,今天把自己想法加上. eval("{a:1}"); eval("{a:,b:1}"); 第一眼的感觉是都会得到一个对象,其 ...
- springmvc学习第四天
数据类型的转换.格式化.校验 1.数据绑定流程 1. Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创 ...