我们知道,我们通过调用线程的start方法启动一个线程,那么,我们可以直接调用run方法来启动一个线程吗?

先看下面一段代码:

  1. public class Test {
  2. public static void main(String[] args) {
  3. // TODO Auto-generated method stub
  4. TestThread tt = new TestThread();
  5. tt.run();
  6. }
  7. }
  8. class TestThread extends Thread {
  9. static int i = 0;
  10. final static int MAX_I = 10;
  11. @Override
  12. public void run() {
  13. // TODO Auto-generated method stub
  14. while (i < MAX_I) {
  15. System.out.println(i++);
  16. }
  17. }
  18. }

运行结果如下:

  1. 0
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9

或许有人会得出结论,这样启动一个线程是可以的,我们再对程式稍做修改,大家就会发现一个问题:

  1. public class Test {
  2. public static void main(String[] args) {
  3. // TODO Auto-generated method stub
  4. TestThread tt = new TestThread();
  5. tt.run();
  6. System.out.println("Printed by main thread");
  7. }
  8. }
  9. class TestThread extends Thread {
  10. static int i = 0;
  11. final static int MAX_I = 10;
  12. @Override
  13. public void run() {
  14. // TODO Auto-generated method stub
  15. while (i < MAX_I) {
  16. System.out.println(i++);
  17. }
  18. }
  19. }

这里只在主线程中加入了一行代码,打印一行"Printed by main thread",运行代码,结果如下:

  1. 0
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9
  11. Printed by main thread

熟练多线程开发的要发现问题了,为什么"Printed by main thread"会打印在最后一行呢?TestThread类中一直持有时间段吗?

我们对上面的代码进行分析,其实非常简单,这只是一个普通的类中方法的调用,其实是一个单线程的执行,我们来修改代码进一步验证这一点:

  1. public class Test {
  2. public static void main(String[] args) {
  3. // TODO Auto-generated method stub
  4. TestThread tt = new TestThread();
  5. tt.run();
  6. System.out.println(Thread.currentThread().getName());
  7. System.out.println("Printed by main thread");
  8. }
  9. }
  10. class TestThread extends Thread {
  11. static int i = 0;
  12. final static int MAX_I = 10;
  13. @Override
  14. public void run() {
  15. // TODO Auto-generated method stub
  16. System.out.println(Thread.currentThread().getName());
  17. while (i < MAX_I) {
  18. System.out.println(i++);
  19. }
  20. }
  21. }

这段代码分别在主线程和我们的TestThread的方法中打印当前线程名字,运行结果如下:

  1. main
  2. 0
  3. 1
  4. 2
  5. 3
  6. 4
  7. 5
  8. 6
  9. 7
  10. 8
  11. 9
  12. main
  13. Printed by main thread

在TestThread类和主线程中运行的是同一个线程,说明在直接调用run时是不能使用多线程的,那么把上面的run方法调用改为start方法的调动再看一下:

  1. public class Test {
  2. public static void main(String[] args) {
  3. // TODO Auto-generated method stub
  4. TestThread tt = new TestThread();
  5. tt.start();
  6. System.out.println(Thread.currentThread().getName());
  7. System.out.println("Printed by main thread");
  8. }
  9. }
  10. class TestThread extends Thread {
  11. static int i = 0;
  12. final static int MAX_I = 10;
  13. @Override
  14. public void run() {
  15. // TODO Auto-generated method stub
  16. System.out.println(Thread.currentThread().getName());
  17. while (i < MAX_I) {
  18. System.out.println(i++);
  19. }
  20. }
  21. }

运行结果如下:

  1. main
  2. Thread-0
  3. 0
  4. 1
  5. 2
  6. 3
  7. 4
  8. 5
  9. 6
  10. 7
  11. 8
  12. Printed by main thread
  13. 9

很明显,这才是我们想看到的结果,所以结论是只有调用Thread的start方法,将线程交由JVM控制,才能产生多线程,而直接调用run方法只是一个普通的单线程程式。

Java start和run启动线程的区别的更多相关文章

  1. Java Thread 的 run() 与 start() 的区别

    Java Thread 的使用 Java Thread 的 run() 与 start() 的区别 Java Thread 的 sleep() 和 wait() 的区别             1. ...

  2. Java并发编程:Java Thread 的 run() 与 start() 的区别

    1. sleep 和 wait 方法解释 sleep()方法是Thread类里面的,主要的意义就是让当前线程停止执行,让出cpu给其他的线程,但是不会释放对象锁资源以及监控的状态,当指定的时间到了之后 ...

  3. java Thread 类 run 和 start 方法区别

    public class ThreadModle { public static void main(String[] args) throws InterruptedException { Thre ...

  4. Java中Thread方法启动线程

    public class ThreadTest extends Thread {  private int count = 10; @Override public void run() { //重写 ...

  5. Java Thread 的 sleep() 和 wait() 的区别

    Java Thread 的使用 Java Thread 的 run() 与 start() 的区别 Java Thread 的 sleep() 和 wait() 的区别       1. sleep ...

  6. Java线程Run和Start的区别

    先上结论:run只是Thread里面的一个普通方法,start是启动线程的方法.何以见得呢?可以执行下面的代码看看run和start的区别: package com.basic.thread; /** ...

  7. 启动线程,start和run的区别

    每个线程都有要执行的任务.线程的任务处理逻辑可以在Tread类的run实例方法中直接实现或通过该方法进行调用,因此 run()相当于线程的任务处理逻辑的入口方法,它由Java虚拟机在运行相应线程时直接 ...

  8. JAVA面试题 启动线程是start()还是run()?为什么?

    面试官:请问启动线程是start()还是run()方法,能谈谈吗? 应聘者:start()方法 当用start()开始一个线程后,线程就进入就绪状态,使线程所代表的虚拟处理机处于可运行状态,这意味着它 ...

  9. java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器

    多线程并发就像是内功,框架都像是外功,内功不足,外功也难得精要. 1.进程和线程的区别 一个程序至少有一个进程,一个进程至少有一个线程. 用工厂来比喻就是,一个工厂可以生产不同种类的产品,操作系统就是 ...

随机推荐

  1. 【leetcode刷题笔记】Sqrt(x)

    Implement int sqrt(int x). Compute and return the square root of x. 题解:二分的方法,从0,1,2.....x搜索sqrt(x)的值 ...

  2. 每天一个linux命令(10):touch命令

    版权声明更新:2017-05-14博主:LuckyAlan联系:liuwenvip163@163.com声明:吃水不忘挖井人,转载请注明出处! 1 文章介绍 本文介绍了Linux下面的mv命令. 2. ...

  3. ACM学习历程—HDU1041 Computer Transformation(递推 && 大数)

    Description A sequence consisting of one digit, the number 1 is initially written into a computer. A ...

  4. 排成一行的li之间的间隙问题

    现象 对于ul下li排成一行的布局(即li的display由list-item设为inline-block): 情况1 如果这些li在书写的时候有换行或者有空格,且ul本身的font-size不为0, ...

  5. 编写dockerfile

    参考:http://www.cnblogs.com/liuyansheng/p/6098470.html 一.dockerfile介绍: 是一种被Docker程序解释的脚本,Dockerfile由一条 ...

  6. UILabel UiButton 文字下面加下划线

    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"直接进入" ...

  7. 优化Java堆大小的5个技巧

    本文作者Pierre是一名有10多年经验的高级系统架构师,他的主要专业领域是Java EE.中间件和JVM技术.根据他多年的工作实践经验,他发现许多性能问题都是由Java堆容量不足和调优引起的.下面他 ...

  8. JSP标签和EL表达式

    1.jsp标签: sun原生的,直接jsp使用 <jsp:include> -- 实现页面包含,动态包含 <jsp:include page="/index.jsp&quo ...

  9. Android Studio的Android Monitor窗口中把标签拉出来之后放不回去的解决方法

    不小心把下图方框中的logcat标签拖出来之后, 就变成了图2的浮动窗口,发现logcat标签怎么也弄不回原来窗口中的位置中. 其实解决方法很简单,只要拖住下图浮动窗口中红框位置的logcat标签,然 ...

  10. [原创] 新人分享--ORA-01012:not logged on的解决办法 [复制链接]

    转自:http://f.dataguru.cn/thread-82530-1-1.html