A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 唐巍 黑马帝   /  2012-3-14 01:39  /  1823 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

进程和线程有什么区别?在创建线程时,不管继承Thread类还是实现Runnable接口为什么都要覆盖Thread类中的run方法?继承Thread类和实现Runnable接口创建线程时两者有什么不同?用哪一种创建线程更好呢?

7 个回复

倒序浏览
方法 run 的常规协定是,它可能执行任何所需的操作。
可以看看API,上面有很多解释
回复 使用道具 举报
进程:是一个正在执行中的程序。
                  每一个进程执行都有一个执行顺序,该顺序是一个执行路径,
                  或者叫一个控制单元。
        线程:就是进程中的一个独立的控制单元。
                  线程在控制着进程的执行。
        一个进程中至少有一个线程。
        start()方法的作用:1,启动线程 2,调用run()方法
        多线程特点:随机性,谁抢到谁执行,至于执行多长时间由cpu说了算。
                原因是多个线程都获取cpu的执行权,cpu执行到谁,谁就运行。
                注:在某一个时刻,只能有一个程序在运行(多核除外)
                可以理解为多线程的运行行为时在互相抢夺cpu的执行权。
    为什么要覆盖run方法?
                THread类用于描述线程。该类就定义了一个功能,用于存储线程
                的运行代码,该存储功能就是run方法。也就是说thread类中的
                run方法是用于存储线程要运行的代码。所以复写run方法就是将
                自定义的代码存储在run方法中,让线程运行。

        Runnable接口
          1,定义类实现Runnable接口
          2,覆盖Runnable接口中的run方法
                        将线程要运行的代码存放在run方法中。
          3,通过Thread类建立线程对象。
          4,将Runnable接口的子类对象作为实际参数传递给Ttread类的构造函数
                        为什么要将Runnable接口的子类对象传递给thread的构造函数?
                        因为,自定义的run方法所属的对象是Runnable接口的子类对象,
                        所以要让线程去指定指定对象的run方法,就必须明确该run方法所属的对象。
                        而thread类的构造方法之一是  Thread(Runnable r){}
          5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法
        实现方式和继承方式的区别
                实现方式的好处:避免了单继承的局限性。推荐使用实现方式。
                继承方式线程代码存放在Thread子类run方法中,而实现方法存放在
                                  就扣的子类run方法中。
回复 使用道具 举报
进程就是一个运行中的程序, 一个进程中可以有多个线程,线程是CPU调度和分派的基本单位, 可以理解为线程就是程序运行中的一条路径;
多个线程并发执行, 提高程序运行效率;
Thread 要继承, 而Runnable 是实现, 两者的区别是:  1:  继承Thread: 线程代码存放在Thread子类的run()方法之中; 定义类继承Thread, 重写run()方法, 创建对象调用start()方法,开启线程并调用run()方法;
                                                                       2:  实现Runnable: 线程代码存放在接口子类的run()方法之中; 实现Runnable 接口,重写Runnable接口中的run()方法,将要运行的代码存放在run()方法中, 通过Thread类建立线程对象,将Runnable的子类对象作为实参穿给Thread的构造函数, 调用Thread类的start()方法开启线程并调用Runnable子类的run()方法; 之所以要将Runnable的子类对象船给Thread,就是因为run()方法所属的对象是Runnable的子类对象, 所以要让线程去指定对象的run()方法, 就必须明确该run()方法所属对象;

我建议用实现的方式创建线程, 因为实现的方式避免了单继承的极限性;
回复 使用道具 举报
崔岩 来自手机 中级黑马 2012-3-14 08:35:01
报纸
本帖最后由 崔岩 于 2012-3-14 08:39 编辑

我用点通俗的话给你讲吧,联系下现实生活。进程呢,可以理解为一个应用程序。比如一场足球赛模拟程序,整个程序就是一个进程。而这个程序中呢,肯定要有若干个球员实例,每个球员就是一个进程。那么对应到程序里呢,球员就是thread的子类。 你说的关于thread 和 runnable的区别。 我们还是结合球赛来讲,球场上肯定只有一个足球对吧?那么这个足球就是一个所有进程共用的资源。每个球员必须要有踢球这个方法,这个方法必须要调用足球这个资源,因此问题就来了,当一个进程(球员)拿到球以后,其他的进程必须要等他主动或者被动的释放这个球,才能让自己的踢球方法运行起来。这也就是进程的互斥问题。 下面我们用面向对象的方法来设计各个对象。球员: public class player extend Thread 足球: public class football implement Runnable { private Object obj ; run()//代表球被获取的方法,并且在这里加同步锁obj,序运行时候,必须只new一个足球实例,new出多个球员,而Thread(runnable)类的构造函数中,恰巧可以传一个runnable对象进去,此例中就是new player(football)。这样可以保证足球只有一个,把球作为参数传给球员,在调用player.start方法。因此obj对象实例也只有一个,所有球员使用的都是同一个锁,这样才能保证球员间的互斥,同时只有一个球员拿到球。 run方法里就是我们需要对共享资源(足球)进行操作的代码。 试想下如果把锁声明在thread里,那new出来多个对象以后,大家用的不是一个锁,不就实现不了同步了么。
回复 使用道具 举报
1.进程和线程的区别:
进程至少包含一个线程,它可以有多个线程。进程就是程序运行时的名字,它是程序的运行时的一个标识。
线程就是控制程序运行。程序的运行其实是线程的执行。
2.Thread和Runnable都要重写run()方法
api规定Thread要继承Runnable接口,而Runnable接口下有个run()方法,所以这两个都是重写run()方法。
3.创建线程有何不同
Thread使用方法:
   class PrimeThread extends Thread {
         long minPrime;
         PrimeThread(long minPrime) {
             this.minPrime = minPrime;
         }
         public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }
Runnable使用方法:
public class RunnableTest implements Runnable {
         
           public void run() {
                ....
           }
}
最后都用start()方法启动线程。
4.用哪一种创建线程更好
Thread:
Thread子类无法再从其它类继承(java语言的单继承),编写简单,run()方法的当前对象就是线程对象,可直接操作。
Runnable:
可以将CPU,代码和数据分开,形成清晰的模型;线程体run()方法所在的类可以从其它类中继承一些有用的属性和方法;有利于保持程序的设计风格一致。
各有优缺点。
回复 使用道具 举报
从概念上:
进程:一个程序对一个数据集的动态执行过程,是分配资源的基本单位。
线程:一个进程内的基本调度单位。
线程的划分尺度小于进程,一个进程包含一个或者更多的线程。

从执行过程中来看:
进程:拥有独立的内存单元,而多个线程共享内存,从而提高了应用程序的运行效率。
线程:每一个独立的线程,都有一个程序运行的入口、顺序执行序列、和程序的出口。但是线程不能够独立的执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

从逻辑角度来看:(重要区别)
多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但是,操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理及资源分配。

创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法,另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。

使用Runnable接口创建线程

1.可以将CPU,代码和数据分开,形成清晰的模型

2.线程体run()方法所在的类可以从其它类中继承一些有用的属性和方法

3.有利于保持程序的设计风格一致

  直接继承Thread类创建对象

1.Thread子类无法再从其它类继承(java语言单继承)。

2.编写简单,run()方法的当前对象就是线程对象,可直接操作。

在实际应用中,几乎都采取第一种方式
回复 使用道具 举报
OMG 中级黑马 2012-3-14 10:46:00
8#
我想您的疑问有以下几点:
1,为什么会出现进程和线程的概念?
2,为什么必须把要执行的代码封装到run()方法中?
3,用类好还是用接口好?
首先,进程和线程,这需要提到cpu。cpu其实不是同时处理多个软件,而是一次只能执行一个程序中的一个对象的代码,并且做瞬间切换,感官上觉得好像是同时运行而已。当我们打开很多页码,同时听歌,下载,复制,移动,玩游戏,为什么会出现卡的现象?对象多,cpu切换周期过长所致。
其次,进程是一个程序,而线程是一个对象。从效率上来说,要快速完成任务,最好是让多个对象共同完成;
再次,为什么要把代码封装到run方法中呢?要实现多个对象独立运行,是需要对对象进行处理的,而对应的处理办法已经封装到start()方法中。而start()方法只认run()方法,只处理run()中的内容,所以,必须把要执行的代码写在run方法中。
最后,继承Thread类好还是实现RunnAble好呢?这是类与接口的区别,请问,如果你写的这个类,已经有父类了,你还能继承Thread类吗?就不能了。还好,可以实现Runnable接口。所以,在定义一个类时,还不清楚它是否要继承某个类的话,那就是用Runnable接口吧。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马