副标题#e#
对付Java开拓人员,多线程应该是必需纯熟应用的常识点,出格是开拓基于 Java语言的产物。本文将深入浅出的表述Java多线程的常识点,在后续的系列里 将偏重于Java5由Doug Lea传授提供的Concurrent并行包的设计思想以及详细实 现与应用。
如何才气深入浅出呢,我的领略是带着问题,而不是平常的看。所以该系列 根基以办理问题为主,虽然我也很是但愿读者可以或许提出更好的办理问题的方案以 及提出更多的问题。由于程度有限,假如有什么错误之处,请各人提出,配合讨 论,总之,我但愿通过该系列我们可以或许深入领略Java多线程来办理我们实际开拓 的问题。
作为开拓人员,我想没有须要接头多线程的基本常识,好比什么是线程?如何建设等 ,这些常识点是可以通过书本和Google得到的。本系列主要是如何理 深入解多线程来辅佐我们平时的开拓,好比线程池如何实现?如何应用锁等。
(1)要领Join是干啥用的? 简朴答复,同步,如何同步? 怎么实现的? 下面将逐个答复。
自从打仗Java多线程,一直对Join领略不了。JDK是这样说的:
join
public final void join(long millis)throws InterruptedException
Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
各人能领略吗? 字面意思是期待一段时间直到这个线程灭亡,我的疑问是那 个线程,是它自己的线程照旧挪用它的线程的,上代码:
package concurrentstudy;
/**
*
* @author vma
*/
public class JoinTest {
public static void main(String[] args) {
Thread t = new Thread(new RunnableImpl());
t.start();
try {
t.join(1000);
System.out.println("joinFinish");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class RunnableImpl implements Runnable {
@Override
public void run() {
try {
System.out.println("Begin sleep");
Thread.sleep(1000);
System.out.println("End sleep");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
功效是:
Begin sleep
End sleep
joinFinish
#p#副标题#e#
大白了吧,当main线程挪用t.join时,main线程期待t线程,期待时间是1000 ,假如t线程Sleep 2000呢
public void run() {
try {
System.out.println("Begin sleep");
// Thread.sleep(1000);
Thread.sleep(2000);
System.out.println("End sleep");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
功效是:
Begin sleep
joinFinish
End sleep
也就是说main线程只等1000毫秒,不管T什么时候竣事,假如是t.join()呢, 看代码:
public final void join() throws InterruptedException {
join(0);
}
就是说假如是t.join() = t.join(0) 0 JDK这样说的 A timeout of 0 means to wait forever 字面意思是永远期待,是这样吗?
其实是比及t竣事后。
这个是怎么实现的吗? 看JDK代码:
/**
* Waits at most <code>millis</code> milliseconds for this thread to
* die. A timeout of <code>0</code> means to wait forever.
*
* @param millis the time to wait in milliseconds.
* @exception InterruptedException if any thread has interrupted
* the current thread. The <i>interrupted status</i> of the
* current thread is cleared when this exception is thrown.
*/
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
#p#分页标题#e#
其实Join要领实现是通过wait(小提示:Object 提供的要领)。 当main线 程挪用t.join时候,main线程会得到线程工具t的锁(wait 意味着拿到该工具的 锁),挪用该工具的wait(期待时间),直到该工具叫醒main线程,好比退出后。
这就意味着main 线程挪用t.join时,必需可以或许拿到线程t工具的锁,假如拿 不到它是无法wait的,刚开的例子t.join(1000)不是说明白main线程期待1秒, 假如在它期待之前,其他线程获取了t工具的锁,它期待时间可不就是1毫秒了。 上代码先容:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package concurrentstudy;
/**
*
* @author vma
*/
public class JoinTest {
public static void main(String[] args) {
Thread t = new Thread(new RunnableImpl());
new ThreadTest(t).start();
t.start();
try {
t.join();
System.out.println("joinFinish");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ThreadTest extends Thread {
Thread thread;
public ThreadTest(Thread thread) {
this.thread = thread;
}
@Override
public void run() {
holdThreadLock();
}
public void holdThreadLock() {
synchronized (thread) {
System.out.println("getObjectLock");
try {
Thread.sleep(9000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("ReleaseObjectLock");
}
}
}
class RunnableImpl implements Runnable {
@Override
public void run() {
try {
System.out.println("Begin sleep");
Thread.sleep(2000);
System.out.println("End sleep");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在main要领中 通过new ThreadTest(t).start();实例化ThreadTest 线程对 象, 它在holdThreadLock()要领中,通过 synchronized (thread),获取线程 工具t的锁,并Sleep(9000)后释放,这就意味着,纵然
main要领t.join(1000),期待一秒钟,它必需期待ThreadTest 线程释放t锁后 才气进入wait要领中,它实际期待时间是9000+1000 MS
运行功效是:
getObjectLock
Begin sleep
End sleep
ReleaseObjectLock
joinFinish
小结:
本节主要深入浅出join及JDK中的实现。