2015-04-23 58 views
1

嗨,我正在学习和玩java中的线程。我在一本书中看到Thread对象和Running Thread不是同一件事。即使线程完成它的运行方法,运行线程也会进入死亡状态,我甚至用isAlive()方法检查它。我想知道,如果两者都不同,那么下面的代码不能按照我的理解工作。Java线程对象vs正在运行线程

public class Main { 

    public static void main(String[] args) throws ParseException { 
     Student s = new Student(); 

     Thread t = new Thread(s); 

     t.start(); 
     t.run(); 
     t.run(); 
     t.run(); 

     t.run(); 
     t.run(); 

    } 
} 

class Student implements Runnable { 
    public void run() { 

     try { 
      Thread.sleep(1000); 
      System.out.println(Thread.currentThread().getName()); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

} 

它只显示这个输出。 主要 线程0 主要 或本 线程0 主要

从这个结果我明白线程之后完成它的运行方式。正在运行的线程进入死态,并调用Thread obj方法不工作,但我无法理解背后的原因,因为Thread对象是技能参考,Thread类的其他方法又如何。 like yield()? start()?

这里是另一种情形了清晰的认识我的话

public class Main { 

    public static void main(String[] args) throws ParseException { 
     Student s = new Student(); 

     Thread t = new Thread(s); 

     t.start(); 

     if (!t.isAlive()) { 

      t.start(); 
     } 

    } 
} 

class Student implements Runnable { 
    public void run() { 

     try { 
      Thread.sleep(1000); 
      System.out.println(Thread.currentThread().getName()); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

} 

文件说,如果我们调用start方法对线程t对象,然后它会抛出java.lang.IllegalThreadStateException。但上面的代码工作正常。 我很困惑Thread类的哪些方法依赖于运行线程和线程对象。我希望你能理解这个问题。 在此先感谢?

回答

2

t.start()启动线程后右,这种情况:

if (!t.isAlive()) 

是veeeeeeeeeeeeeeeeeeery不可能实现 - 因为开始线程不会阻塞。这就是为什么它只是跳过(因为t.isAlive() == true),并进一步没有例外。

+0

我知道大部分时间它不会发生,但为什么运行和其他方法仍然不起作用我的第一个代码 –

+0

,因为't'已经在第一次调用't'时使用了'Runnable s' 。开始()'。 –

+0

“如果此线程是使用单独的Runnable运行对象构造的,那么将调用该Runnable对象的运行方法; *否则,此方法不执行任何操作并返回。*”--https://docs.oracle.com/javase/7 /docs/api/java/lang/Thread.html#run%28%29 –

2

你可以在两个方面做到这一点。这几乎是一样的。你应该开始在你的第一个代码文件中的线程只是一个简单的

t.start(); 

我会从你上面的代码删除所有t.run(),因为您要建立与实施内部类新Thread对象。

+0

'run'方法不启动线程。 – CKing

+0

实现内部类的第一件事学生类是独立的类。其次,我多次调用run方法来知道为什么这个方法没有被调用,因为它只是简单的对象驻留在堆上,它仍然指向并且反对场景故事背后的原因。 –

+0

但是这个代码看起来很无用。 – Norukh

2

在你的第一次尝试,你永远不会重新启动线程:

t.start(); 
t.run();// does not restarts the thread, it simply makes synchronous call the run(), hence you don't get the exception 
t.start();// add this line, to restart the thread and get the exception 

在第二次尝试,因为线程可能开始又活的,按你的条件线程不能活着,它的条件失败无法重新启动线程。

t.start(); 
t.join();// add this line, it allows thread to complete first 
if (!t.isAlive()) { 
    t.start(); 
} 

P.S.

为了启动一个线程拨打电话start(),这将导致异步呼叫run()。如果你打电话给run(),它不会以线程启动,它会像普通方法调用一样进行同步调用。

+0

好的Arvind我明白了,但我不明白为什么会发生。因为我运行它扩展Thread类我开始调用run方法很多时间和它的工作原理。 –

+0

@Arvind你不能在同一个'Thread'上两次调用'start()'。 – artaxerxe

+0

@artaxerxe,请仔细阅读OP文章,OP问为什么没有运行时错误? – Arvind

1

在您提供的第一个例子,程序不显示等于你t.start() + t.run()调用线程名称的计数的原因是,后一个线程是死了,你不能在它start()run()再打电话。它已经死了。有3个输出的原因可能是因为直到t.start()进入死状态,其他2个调用才能执行。

在第二个示例中,您应该知道,调用start()时,线程状态将处于活动状态。无论如何,在并发环境中,如果不涉及​​,则无法依赖操作调用顺序,但从得到的结果来看,似乎t.start()在调用t.isAlive()之前被调用。 希望能提供帮助。

+0

如果我从线程类延伸到线程已死亡后,如何处理。它的运行方法正在工作 –

+0

@ T.Malik您无法从对象中扩展。你从一个班级延伸。请更确切地说,如果我不明白的话。 – artaxerxe

+0

嗯好吧,我明白了。谢谢 –

0

我在一本书中读到Thread对象和Running Thread是不一样的东西。

对,“线程”是您的代码的执行。 A Thread是一个Java对象,可用于创建和管理“线程”的生命周期。直到调用Thread对象的.start()方法,并且Thread对象即使在“线程”完成其工作并消失后仍然可以继续存在,“线程”才会创建。