您的位置:首页 > 编程语言 > Java开发

Java多线程--wait和join

2015-07-08 23:45 453 查看
首先从公司一道笔试题开始

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));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: