Java知多少isAlive和join的fork join 使用场景

Java线程中yield与join方法的区别 - ImportNew
长期以来,多线程问题颇为受到面试官的青睐。虽然我个人认为我们当中很少有人能真正获得机会开发复杂的多线程应用(在过去的七年中,我得到了一个机会),但是理解多线程对增加你的信心很有用。之前,我讨论了一个wait()和sleep()方法区别的问题,这一次,我将会讨论join()和yield()方法的区别。坦白的说,实际上我并没有用过其中任何一个方法,所以,如果你感觉有不恰当的地方,请提出讨论。
Java线程调度的一点背景
在各种各样的线程中,Java虚拟机必须实现一个有优先权的、基于优先级的调度程序。这意味着Java程序中的每一个线程被分配到一定的优先权,使用定义好的范围内的一个正整数表示。优先级可以被开发者改变。即使线程已经运行了一定时间,Java虚拟机也不会改变其优先级
优先级的值很重要,因为Java虚拟机和下层的操作系统之间的约定是操作系统必须选择有最高优先权的Java线程运行。所以我们说Java实现了一个。该调度程序使用一种有优先权的方式实现,这意味着当一个有更高优先权的线程到来时,无论低优先级的线程是否在运行,都会中断(抢占)它。这个约定对于操作系统来说并不总是这样,这意味着操作系统有时可能会选择运行一个更低优先级的线程。(我憎恨多线程的这一点,因为这不能保证任何事情)
注意Java并不限定线程是以时间片运行,但是大多数操作系统却有这样的要求。在术语中经常引起混淆:抢占经常与时间片混淆。事实上,抢占意味着只有拥有高优先级的线程可以优先于低优先级的线程执行,但是当线程拥有相同优先级的时候,他们不能相互抢占。它们通常受时间片管制,但这并不是Java的要求。
理解线程的优先权
接下来,理解线程优先级是多线程学习很重要的一步,尤其是了解yield()函数的工作过程。
记住当线程的优先级没有指定时,所有线程都携带普通优先级。
优先级可以用从1到10的范围指定。10表示最高优先级,1表示最低优先级,5是普通优先级。
记住优先级最高的线程在执行时被给予优先。但是不能保证线程在启动时就进入运行状态。
与在线程池中等待运行机会的线程相比,当前正在运行的线程可能总是拥有更高的优先级。
由调度程序决定哪一个线程被执行。
t.setPriority()用来设定线程的优先级。
记住在线程开始方法被调用之前,线程的优先级应该被设定。
你可以使用常量,如MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY来设定优先级
现在,当我们对线程调度和线程优先级有一定理解后,让我们进入主题。
yield()方法
理论上,yield意味着放手,放弃,投降。一个调用yield()方法的线程告诉虚拟机它乐意让其他线程占用自己的位置。这表明该线程没有在做一些紧急的事情。注意,这仅是一个暗示,并不能保证不会产生任何影响。
在Thread.java中yield()定义如下:
* A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore
* this hint. Yield is a heuristic attempt to improve relative progression between threads that would otherwise over-utilize a CPU.
* Its use should be combined with detailed profiling and benchmarking to ensure that it actually has the desired effect.
public static native void yield();
让我们列举一下关于以上定义重要的几点:
Yield是一个静态的原生(native)方法
Yield告诉当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程。
Yield不能保证使得当前正在运行的线程迅速转换到可运行的状态
它仅能使一个线程从运行状态转到可运行状态,而不是等待或阻塞状态
yield()方法使用示例
在下面的示例程序中,我随意的创建了名为生产者和消费者的两个线程。生产者设定为最小优先级,消费者设定为最高优先级。在Thread.yield()注释和非注释的情况下我将分别运行该程序。没有调用yield()方法时,虽然输出有时改变,但是通常消费者行先打印出来,然后事生产者。
调用yield()方法时,两个线程依次打印,然后将执行机会交给对方,一直这样进行下去。
package test.core.
public class YieldExample
public static void main(String[] args)
Thread producer = new Producer();
Thread consumer = new Consumer();
producer.setPriority(Thread.MIN_PRIORITY); //Min Priority
consumer.setPriority(Thread.MAX_PRIORITY); //Max Priority
producer.start();
consumer.start();
class Producer extends Thread
public void run()
for (int i = 0; i & 5; i++)
System.out.println(&I am Producer : Produced Item & + i);
Thread.yield();
class Consumer extends Thread
public void run()
for (int i = 0; i & 5; i++)
System.out.println(&I am Consumer : Consumed Item & + i);
Thread.yield();
上述程序在没有调用yield()方法情况下的输出:
I am Consumer : Consumed Item 0
I am Consumer : Consumed Item 1
I am Consumer : Consumed Item 2
I am Consumer : Consumed Item 3
I am Consumer : Consumed Item 4
I am Producer : Produced Item 0
I am Producer : Produced Item 1
I am Producer : Produced Item 2
I am Producer : Produced Item 3
I am Producer : Produced Item 4
上述程序在调用yield()方法情况下的输出:
I am Producer : Produced Item 0
I am Consumer : Consumed Item 0
I am Producer : Produced Item 1
I am Consumer : Consumed Item 1
I am Producer : Produced Item 2
I am Consumer : Consumed Item 2
I am Producer : Produced Item 3
I am Consumer : Consumed Item 3
I am Producer : Produced Item 4
I am Consumer : Consumed Item 4
join()方法
线程实例的方法join()方法可以使得一个线程在另一个线程结束后再执行。如果join()方法在一个线程实例上调用,当前运行着的线程将阻塞直到这个线程实例完成了执行。
//Waits for this thread to die.
public final void join() throws InterruptedException
在join()方法内设定超时,使得join()方法的影响在特定超时后无效。当超时时,主方法和任务线程申请运行的时候是平等的。然而,当涉及sleep时,join()方法依靠操作系统计时,所以你不应该假定join()方法将会等待你指定的时间。
像sleep,join通过抛出InterruptedException对中断做出回应。
join()方法使用示例
package test.core.
public class JoinExample
public static void main(String[] args) throws InterruptedException
Thread t = new Thread(new Runnable()
public void run()
System.out.println(&First task started&);
System.out.println(&Sleeping for 2 seconds&);
Thread.sleep(2000);
} catch (InterruptedException e)
e.printStackTrace();
System.out.println(&First task completed&);
Thread t1 = new Thread(new Runnable()
public void run()
System.out.println(&Second task completed&);
t.start(); // Line 15
t.join(); // Line 16
t1.start();
First task started
Sleeping for 2 seconds
First task completed
Second task completed
这是一些很小却很重要的概念。在评论部分让我知道你的想法。
原文链接:
- 译文链接: [ 转载请保留原文出处、译者和译文链接。]
关于作者:
软件工程系大三生,喜欢看书,文学+技术,感兴趣的方向:web、模式识别,编程语言Java
如需兼职或实习生,请Email我:
可能感兴趣的文章
可以把天气相关的三个类分离出抽象类出来
关于ImportNew
ImportNew 专注于 Java 技术分享。于日 11:11正式上线。是的,这是一个很特别的时刻 :)
ImportNew 由两个 Java 关键字 import 和 new 组成,意指:Java 开发者学习新知识的网站。 import 可认为是学习和吸收, new 则可认为是新知识、新技术圈子和新朋友……
新浪微博:
推荐微信号
反馈建议:@
广告与商务合作QQ:
– 好的话题、有启发的回复、值得信赖的圈子
– 写了文章?看干货?去头条!
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 活跃 & 专业的翻译小组
– 国内外的精选博客文章
– UI,网页,交互和用户体验
– JavaScript, HTML5, CSS
– 专注Android技术分享
– 专注iOS技术分享
– 专注Java技术分享
– 专注Python技术分享
& 2017 ImportNewJava线程编程中isAlive()和join()的使用详解-爱编程
Java线程编程中isAlive()和join()的使用详解
一个线程如何知道另一线程已经结束?Thread类提供了回答此问题的方法。
有两种方法可以判定一个线程是否结束。第一,可以在线程中调用isAlive()。这种方法由Thread定义,它的通常形式如下:
final boolean isAlive( )
如果所调用线程仍在运行,isAlive()方法返回true,如果不是则返回false。但isAlive()很少用到,等待线程结束的更常用的方法是调用join(),描述如下:
final void join( ) throws InterruptedException
该方法等待所调用线程结束。该名字来自于要求线程等待直到指定线程参与的概念。join()的附加形式允许给等待指定线程结束定义一个最大时间。下面是前面例子的改进版本。运用join()以确保主线程最后结束。同样,它也演示了isAlive()方法。
// Using join() to wait for threads to finish.
class NewThread implements Runnable {
S // name of thread
NewThread(String threadname) {
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
// This is the entry point for thread.
public void run() {
for(int i = 5; i & 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
System.out.println(name + " exiting.");
class DemoJoin {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
NewThread ob3 = new NewThread("Three");
System.out.println("Thread One is alive: "+ ob1.t.isAlive());
System.out.println("Thread Two is alive: "+ ob2.t.isAlive());
System.out.println("Thread Three is alive: "+ ob3.t.isAlive());
// wait for threads to finish
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
System.out.println("Thread One is alive: "+ ob1.t.isAlive());
System.out.println("Thread Two is alive: "+ ob2.t.isAlive());
System.out.println("Thread Three is alive: "+ ob3.t.isAlive());
System.out.println("Main thread exiting.");
程序输出如下所示:
New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
New thread: Thread[Three,5,main]
Thread One is alive: true
Thread Two is alive: true
Thread Three is alive: true
Waiting for threads to finish.
Two exiting.
Three exiting.
One exiting.
Thread One is alive: false
Thread Two is alive: false
Thread Three is alive: false
Main thread exiting.
如你所见,调用join()后返回,线程终止执行。
版权所有 爱编程 (C) Copyright 2012. . All Rights Reserved.
闽ICP备号-3
微信扫一扫关注爱编程,每天为您推送一篇经典技术文章。如前所述,通常你希望主线程最后结束。在前面的例子中,这点是通过在main()中调用sleep()来实现的,经过足够长时间的延迟以确保所有子线程都先于主线程结束。然而,这不是一个令人满意的解决方法,它也带来一个大问题:一个线程如何知道另一线程已经结束?幸运的是,Thread类提供了回答此问题的方法。有两种方法可以判定一个线程是否结束。第一,可以在线程中调用isAlive()。这种方法由Thread定义,它的通常形式如下:& & final boolean isAlive( )如果所调用线程仍在运行,isAlive()方法返回true,如果不是则返回false。但isAlive()很少用到,等待线程结束的更常用的方法是调用join(),描述如下:& & final void join( ) throws InterruptedException该方法等待所调用线程结束。该名字来自于要求线程等待直到指定线程参与的概念。join()的附加形式允许给等待指定线程结束定义一个最大时间。下面是前面例子的改进版本。运用join()以确保主线程最后结束。同样,它也演示了isAlive()方法。
1 // Using join() to wait for threads to finish.
2 class NewThread implements Runnable {
S // name of thread
NewThread(String threadname) {
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
// This is the entry point for thread.
public void run() {
for(int i = 5; i & 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
System.out.println(name + " exiting.");
25 class DemoJoin {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
NewThread ob3 = new NewThread("Three");
System.out.println("Thread One is alive: "+ ob1.t.isAlive());
System.out.println("Thread Two is alive: "+ ob2.t.isAlive());
System.out.println("Thread Three is alive: "+ ob3.t.isAlive());
// wait for threads to finish
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
System.out.println("Thread One is alive: "+ ob1.t.isAlive());
System.out.println("Thread Two is alive: "+ ob2.t.isAlive());
System.out.println("Thread Three is alive: "+ ob3.t.isAlive());
System.out.println("Main thread exiting.");
程序输出如下所示:
New thread: Thread[One,5,main]New thread: Thread[Two,5,main]New thread: Thread[Three,5,main]Thread One is alive: trueThread Two is alive: trueThread Three is alive: trueWaiting for threads to finish.One: 5Two: 5Three: 5One: 4Two: 4Three: 4One: 3Two: 3Three: 3One: 2Two: 2Three: 2One: 1Two: 1Three: 1Two exiting.Three exiting.One exiting.Thread One is alive: falseThread Two is alive: falseThread Three is alive: falseMain thread exiting.如你所见,调用join()后返回,线程终止执行。
系列文章:
阅读(...) 评论()Java多线程系列--“基础篇”08之 join() - 如果天空不死 - 博客园
随笔 - 278
评论 - 917
本章,会对Thread中join()方法进行介绍。涉及到的内容包括:
转载请注明出处:
1. join()介绍
join() 定义在Thread.java中。join() 的作用:让&主线程&等待&子线程&结束之后才能继续运行。这句话可能有点晦涩,我们还是通过例子去理解:
public class Father extends Thread {
public void run() {
Son s = new Son();
s.start();
public class Son extends Thread {
public void run() {
说明:上面的有两个类Father(主线程类)和Son(子线程类)。因为Son是在Father中创建并启动的,所以,Father是主线程类,Son是子线程类。在Father主线程中,通过new Son()新建&子线程s&。接着通过s.start()启动&子线程s&,并且调用s.join()。在调用s.join()之后,Father主线程会一直等待,直到&子线程s&运行完毕;在&子线程s&运行完毕之后,Father主线程才能接着运行。 这也就是我们所说的&join()的作用,是让主线程会等待子线程结束之后才能继续运行&!
2. join()源码分析(基于JDK1.7.0_40)
public final void join() throws InterruptedException {
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()) {
while (isAlive()) {
long delay = millis -
if (delay &= 0) {
wait(delay);
now = System.currentTimeMillis() -
说明:从代码中,我们可以发现。当millis==0时,会进入while(isAlive())循环;即只要子线程是活的,主线程就不停的等待。我们根据上面解释join()作用时的代码来理解join()的用法!问题:虽然s.join()被调用的地方是发生在&Father主线程&中,但是s.join()是通过&子线程s&去调用的join()。那么,join()方法中的isAlive()应该是判断&子线程s&是不是Alive状态;对应的wait(0)也应该是&让子线程s&等待才对。但如果是这样的话,s.join()的作用怎么可能是&让主线程等待,直到子线程s完成为止&呢,应该是让"子线程等待才对(因为调用子线程对象s的wait方法嘛)"?答案:的作用是让&当前线程&等待,而这里的&当前线程&是指当前在CPU上运行的线程。所以,虽然是调用子线程的wait()方法,但是它是通过&主线程&去调用的;所以,休眠的是主线程,而不是&子线程&!
3. join()示例
在理解join()的作用之后,接下来通过示例查看join()的用法。
// JoinTest.java的源码
public class JoinTest{
public static void main(String[] args){
ThreadA t1 = new ThreadA("t1"); // 新建&线程t1&
t1.start();
// 启动&线程t1&
t1.join();
// 将&线程t1&加入到&主线程main&中,并且&主线程main()会等待它的完成&
System.out.printf("%s finish\n", Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
static class ThreadA extends Thread{
public ThreadA(String name){
super(name);
public void run(){
System.out.printf("%s start\n", this.getName());
// 延时操作
for(int i=0; i &1000000; i++)
System.out.printf("%s finish\n", this.getName());
运行结果:
main finish
结果说明:运行流程如图&(01) 在&主线程main&中通过 new ThreadA("t1") 新建&线程t1&。 接着,通过 t1.start() 启动&线程t1&,并执行t1.join()。(02) 执行t1.join()之后,&主线程main&会进入&阻塞状态&等待t1运行结束。&子线程t1&结束之后,会唤醒&主线程main&,&主线程&重新获取cpu执行权,继续运行。
阅读(...) 评论()

我要回帖

更多关于 fork join 使用 的文章

 

随机推荐