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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 刘源 于 2012-7-11 11:58 编辑

     希望高手解下疑惑。Thread中的run()可以继承被start()运行。runnable的子类通过实现run()也可以被运行。然后在和Thread()产生关系,那这个关系是怎么产生的啊,有没有简介点的代码演示下Thread中run()的结构啊。就是想知道,怎么通过一个runnable的子类,和Thread()产生关系,这个关系也是覆盖吗,还是只是要用到start()这个方法。谢谢了

评分

参与人数 1技术分 +1 收起 理由
职业规划-刘倩老师 + 1 加油!!!

查看全部评分

9 个回复

倒序浏览
楼主,下面的代码是毕老师讲多线程时的代码:
start方法只是起到启动线程并调用run方法而已,它是属于Thread对象的方法

class Ticket implements Runnable   //这里的Ticket实现了Runnable接口,
{
        private  int tick = 1000;
        Object obj = new Object();
        public void run()   //重写了run方法
        {
                while(true)
                {
                        synchronized(obj)  // 这里讲代码同步了,以防止多个线程访问时出现数据同时被改写的安全问题
                        {
                                if(tick>0)
                                {
                                        //try{Thread.sleep(10);}catch(Exception e){}
                                        System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
                                }
                        }
                }
        }
}


class  TicketDemo2
{
        public static void main(String[] args)
        {

                Ticket t = new Ticket();//楼主注意看这里,这里创建了一个Ticket对象t

                Thread t1 = new Thread(t);//这里把t作为参数传入Thread方法中,runnable类就是这样和Thread类联系起来的
                Thread t2 = new Thread(t);
                Thread t3 = new Thread(t);
                Thread t4 = new Thread(t);
                t1.start();
                t2.start();
                t3.start();
                t4.start();


        }
}

评分

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

查看全部评分

回复 使用道具 举报
class Demo implements Runnable//1,定义类实现Runnable接口
{
        private  int num = 0;
        public void run()//2,覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。
        {
                while(true)
                {
                                      System.out.println(Thread.currentThread().getName()+" : "+ num++);
                 }
               
        }
}
class  ThreadDemo
{
        public static void main(String[] args)
        {

                Demo d = new Demo();

                Thread t1 = new Thread(d);//3,通过Thread类建立线程对象,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
                t1.start();//4,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。



我们建立线程无非就是为了运行自己想运行的代码,所以run()就提供了一个让我们存放需要多线程运行代码的地方
而start()的作用仅仅只是为了开启线程

评分

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

查看全部评分

回复 使用道具 举报
楼上说的我都知道。毕老师都讲得很清楚。但我想好好理解下,这个runnable和Thread里面的内部run()方法是如何的写的。使Thread既能自己调用run(),又能用runnable的子类通过Thread来使用run()。还是谢谢楼上了。
回复 使用道具 举报
楼主这个问题提得有深度,上面的同学们回答的都不错,但是,我查看了一下源代码和帮助文档,发现事情好像没那么简单
我们来看看文档中对 start方法 的描述:使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
注意,这里说是java虚拟机调用该线程的 run 方法,并不是start方法去调用 run 方法,上面的同学们都说错了!!!
那这个 start 方法到底干了什么呢?我们来看看源代码:
public synchronized void start() {
        /**
     * This method is not invoked for the main method thread or "system"
     * group threads created/set up by the VM. Any new functionality added
     * to this method in the future may have to also be added to the VM.
     *
     * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0 || this != me)                         //start方法没有调用过 run方法
            throw new IllegalThreadStateException();
        group.add(this);
        start0();
        if (stopBeforeStart) {
        stop0(throwableFromStop);
    }
    }

    private native void start0();         //注意这个很奇怪的 start0 方法,他竟然是 native 修饰的

    /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    public void run() {    run方法
    if (target != null) {
        target.run();
    }
    }

根据以上代码我们不难发现,start 方法根本没去调用 run 方法,倒是调用了一个 native 修饰的 start0 方法,那么这个native到底是什么意思呢
我上网查了一下,当java调用本地代码(如 C,C++)的时候,需要使用native修饰
我们知道,windows操作系统是C,C++编写的,也就是说 start0 方法去调用windows代码了
我也不是太懂,但是我做了一个大胆的推测
当我们调用start方法时,java虚拟机会去调用windows的本地代码启动一个线程,然后java虚拟机再在此线程上运行 run 方法中的代码!!!
当然了,这只是我的推测,具体怎样,还望高人解答

评分

参与人数 1技术分 +1 收起 理由
黑马张扬 + 1

查看全部评分

回复 使用道具 举报
Thread类同样实现了Runnable接口,因此要是说Runnable和Tread有什么关系的话也就是这个了
Thread类中的run方法同样是实现了Runnable中的run方法:
public void run() {
        if (target != null) {
            target.run();
        }
    }
其中的target是private Runnable target;这也解释了为什么Tread的构造方法中可以是Runnable类型的
至于start方法是怎么开启线程的,源码中是使用本地方法实现的
private native void start0();
所以具体的,我们也无从得知,毕竟JVM是用C写的,要想知道怎么实现的只有看JVM的源码了
回复 使用道具 举报
回复 使用道具 举报
刘源 中级黑马 2012-7-10 23:58:24
8#
谢谢大家了。特别是高原和张天天,看了你们的答案后。我发现我现在的知识还不够,只能先强行记住了,等以后提高了在去解答,我会把你们的答案剪切下来,以后在看。{:soso_e100:}
回复 使用道具 举报
步骤:
1.定义类实现Runnable接口
2.覆盖Runnable接口中的run方法
        将线程要运行的代码存放在该run方法中
3.通过Thread类建立线程对象。
4.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
        为什么要将Runnable接口的子类对象传递给Thread的构造函数。
        因为,自定义的run方法所属的对象是Runnable接口的子类对象。
        所以要让线程去指定对象的run方法。就必须明确该run方法所属对象。
5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
老师的笔记
回复 使用道具 举报
我自己写了一个了。有兴趣的可以看下,感觉还可以。

interface R1//R1=Runable
{
         void run();
}
class R2 implements R1
{
        public  void  run()
        {
                System.out.println("R2");
       
        }
}
class R3 implements R1//R3= Thread
{
        R3(){}
        private R2 r;
        public void run()
        {
                System.out.println("R3");
        }
        R3(R2 r)
        {
                this.r =r;
        }
        public void dd()//相当于start()
        {
                if(r==null)run();
                else
                        r.run();
        }
}
class R4 extends R3
{
        public void run()
        {
                System.out.println("R3");
        }

}
class  T1
{
        public static void main(String[] args)
        {
                 R2 f = new R2();
                 R3 t =new R3(f);
                 t.dd();//这个是相当于实现Runnable 建的线程。
                 R3 t1 = new R4();
                 t1.dd();//这个是相当于继承Thead 建的线程。
        }
}
这是程序只是简单(自己想当然)的Thread和Runnable与run()方法的关系,至于run和start的关系,暂时技术不够研究。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马