我们知道,我们通过调用线程的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. 【遍历二叉树】09判断二叉树是否关于自己镜像对称【Symmetric Tree】

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个二叉树,判断是否他自己的镜 ...

  2. bzoj1000~1025

    以后还是这样 25道题一起发 看着爽 noip失利之后发粪涂墙 刷了一波bzoj 题解: bzoj1000 A+B问题 这题不同的人有不同的写法,我写了个线段树套Treap,应该还是挺简单的 但是看别 ...

  3. ACM学习历程—HDU 5025 Saving Tang Monk(广州赛区网赛)(bfs)

    Problem Description <Journey to the West>(also <Monkey>) is one of the Four Great Classi ...

  4. CodeForces - 605C 凸包+直线与凸包判交

    题目大意: 要完成两种属性p,q的需求,给定n个双属性物品及其单位个物品中含有的属性,要求选择最少的物品来达成属性需求.(可以选择实数个物品) 题解: 实际上是一种属性混合问题 我们知道对于两种双属性 ...

  5. script加载之defer和async

    详情请查看:http://www.heiboard.com/?p=2098

  6. 命令行启动nodejs方式 小总结

    之前启动nodejs都是写一个命令行文件,如nodejs.cmd,内容为:start node E:\node\app.js. 今天突然想到之前也用过另外一种方式启动,就是在命令行通过cd命令先找到n ...

  7. mount error(12): Cannot allocate memory解决办法

    http://hi.baidu.com/zhangbin101004/item/e459f4d1f818dfbd33db903b 今天囧了啊,在ubuntu挂载的文件夹里面解压数据库,结果linux嫌 ...

  8. tomcat部署虚拟主机-搭建两个应用以及httpd和Nginx的反向代理

    实验环境:CentOS7 前提:已经安装好tomcat,未安装请查看http://www.cnblogs.com/wzhuo/p/7111135.html: 目的:基于主机名访问两个应用: [root ...

  9. 关于KMeans 最外围点移除实验(其中心保持不变)

    import matplotlib.pyplot as plt from sklearn.datasets import make_blobs import numpy as np X,labels ...

  10. 【254】◀▶IEW-Unit19

    Unit 19 Technology Communication I.名词性从句在雅思写作中的运用 英语中哪些位置可以放名词? 1)主语 2)宾语 3)表语 4)同位语 名词的位置放一个句子=名词性从 ...