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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 小飞龙 初级黑马   /  2012-7-19 16:11  /  1976 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

为什么Runnable要实现run方法,而Thread不需要的呢,只需写start方法就行了?

7 个回复

正序浏览
两种实现方式的区别和联系:
  
  以卖票程序为例,通过Thread类完成:
   
   class MyThread extends Thread{
   private int ticket = 10;
   public void run(){
   
   for(int i=0;i<20;i++){
    if(this.ticket>0){
       
         System.out.println("卖票ticket"+this.ticket--);
   }
   }
   }
   }
   下面通过三个线程对象,同时卖票:
   public class ThreadTicket{
   
   public static void main(String[] args){
    MyThread mt1 = new MyThread();
        MyThread mt2 = new MyThread();
        MyThread mt3 = new MyThread();
       
        mt1.start(); //每个线程都各卖了10张,共卖了30张票
        mt2.start(); //但实际只有10张票,每个线程都卖自己的票
        mt3.start(); //没有达到资源共享
       
   }
   }
   
   如果用Runnable就可以实现资源共享,下面看例子:
   
   class MyThread implements Runnable{
   private int ticket =10;
   public void run(){
   for(int i=0;i<20;i++){
   if(this.ticket>0){
   System.out.println("卖票 ticket"+this.ticket--);
   }
   }
   
   }
   }

   public class RunnableTicket{
   public static void main(String[] args){
    MyThread mt = new MyThread();
        new Thread(mt).start(); //同一个mt,但是在Thread中就不可以,
        new Thread(mt).start();
    new Thread(mt).start();
   
   }
   
   };虽然现在程序中有三个线程,但是一共卖了10张票,也就是说使用
   Runnable实现多线程可以达到资源共享目的。
   
   
   Runnable接口和Thread之间的联系:
   
   public class Thread extends Obejct implements Runnable
   发现Thread类也是Runnable接口子类。

评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1

查看全部评分

回复 使用道具 举报
在Threadl类中的run()方法,有Runnable子类完成的,所以要通过继承Thread类实现多线程,则必须覆写run()方法。
实现Runnable接口相对于继承Thread类来说,有如下有点:
1、适合多个相同程序源代码的线程去处理同一资源的情况
2、可以避免由于java的单继承特性带来的局限
3、增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。
回复 使用道具 举报
通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。然后通过此Thread类调用方法run()来完成其运行操作的,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程终止,而CPU再运行其它线程。
    而如果直接用Run方法,这只是调用一个方法而已,程序中依然只有主线程--这一个线程,其程序执行路径还是只有一条,这样就没有达到写线程的目的。
    记住:线程就是为了更好地利用CPU,提高程序运行速率的!
    public class TestThread1{
        public static void main(String[] args){
            Runner1 r=new Runner1();
            //r.run();//这是方法调用,而不是开启一个线程
            Thread t=new Thread(r);//调用了Thread(Runnable target)方法。且父类对象变量指向子类对象。
            t.start();
            for(int i=0;i<100;i++){
                System.out.println("进入Main Thread运行状态");
                System.out.println(i);
            }
        }
    }
    class Runner1 implements Runnable{ //实现了这个接口,jdk就知道这个类是一个线程
        public void run(){
            for(int i=0;i<100;i++){
                System.out.println("进入Runner1运行状态");
                System.out.println(i);
            }
        }
    }

注意:

Runnable接口分析

Java中实现多线程有两种途径:继承Thread类或者实现Runnable接口.
Runnable接口非常简单,就定义了一个方法run(),继承Runnable并实现这个
方法就可以实现多线程了,但是这个run()方法不能自己调用,必须由系统来调用,否则就和别的方法没有什么区别了.
先给一个简单的例子:
public class MultiThread implements Runnable{
public static void main(String[] args){
     for(int i=0;i<10;i++){
        new Thread(new MultiThread()).start();//correct
                 //new Thread(new MultiThread()).run 1
   //new MultiThread().run()       2
     }
}
public void run(){   
     System.out.println(Thread.currentThread().getName());
}
}
运行后应该启动了10个新的线程,加上主线程一共11个线程,应该输出是Thread-1知道10.
这里要注意启动线程的方式是调用了Thread的start()方法,而不是run方法,如果
用注释里的1或者2输入都是10个main,因为这个时候run()方法还原了,和普通方法一样了.
我们也可以得出一个结论:所有的线程在运行时都是一个Thread实例,虽然可以不用继承Thread
实现多线程,但是最终还是Thread的一个实例.



评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 包晗 于 2012-7-19 20:27 编辑

run 方法是存储
start()方法来启动一个线程
start 是用来同步执行的(多线程)  如果把start 换成run  程序也能执行
不过换成start后 就是单线程执行  
参见毕老师的 第11天视频   
start方法会调用自己的run方法


  1. class Thread
  2. void show()
  3. {
  4. for(int i=0;i<1000;i++){
  5. System.out.println("包含是天才吗?");
  6. }
  7. Thread t=new Thread();//
  8. t.start();


  9. for(int i=0;i<1000;i++)
  10. {
  11. System.out.println("包含是天才");
  12. }
  13. }


复制代码
你在DOS 命令行里 就会看见  “ 包含是天才” 与 “ 包含是天才” 交替打印

如果你把start 改成run  你就会看见 先执行  “ 包含是天才吗? ”  再执行“包含是天才 ”
   

评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1 看来你真是天才....

查看全部评分

回复 使用道具 举报
这是实现 多线程的两种方法
实现runnable接口 必须实现run()方法
而继承Thread类的线程机制 不一定要重写其run()方法 线程类将调用基类的run()方法
当然 通过继承Thread类创建的线程 如果 你想让他做你想做的事情 就要 覆盖run()方法了   
回复 使用道具 举报
实现Runnable要覆盖run方法,而继承Thread也是需要覆盖run方法的。
只不过,在启动线程的时候,这两种方法都是使用start方法启动的,不能用run方法启动。
回复 使用道具 举报
好好看看书吧!!继承Thread 要复写run方法
实现Runnable也要复写run方法
你写过start方法吗???只是被调用吧!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马