天天看点

实现并启动线程有两种方法

:相当于玩游戏机,只有一个游戏机(cpu),可是有很多人要玩,于是,start是排队!等cpu选中你就是轮到你,你就run(),当cpu的运行的时间片执行完,这个线程就继续排队,等待下一次的run()。

调用start()后,线程会被放到等待队列,等待cpu调度,并不一定要马上开始执行,只是将这个线程置于可动行状态。然后通过jvm,线程thread会调用run()方法,执行本线程的线程体。先调用start后调用run,这么麻烦,为了不直接调用run?就是为了实现多线程的优点,没这个start不行。

方法来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;通过调用thread类的start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。 然后通过此thread类调用方法run()来完成其运行操作的, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, run方法运行结束, 此线程终止。然后cpu再调度其它线程。

方法当作普通方法的方式调用。程序还是要顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码; 程序中只有主线程——这一个线程, 其程序执行路径还是只有一条, 这样就没有达到写线程的目的。

1.定义runnable接口的实现类,并重写其中的run方法。run()方法的方法体是线程执行体。

2.创建runnable接口实现类的实例。

3.用该实例作为thread的target来创建thread对象。

4.调用该对象的start()方法启动线程。

在创建thread 对象的时候可以为该thread对象指定一个名字

实现并启动线程有两种方法

runnable对象作为thread对象的target,runnable实现类里面包含run方法仅仅作为执行体。也就是说thread类的作用是把run方法包装成线程的执行体。

实际运行的线程对象依然是thread实例,只是该thread线程负责执行其target的run方法。

通过jdk源码解析thread(runable target …)调用的是哪个run方法

首先,我们来看一下jdk的thread源码,片段 3 如下:

在run()方法中,首先会检查target是否为空,如果不是,则执行该target的run()方法。

那么,对于上面两段代码的执行,也就清楚了。

在第一个代码段 1 中,重写了thread的run()方法,同时传入了一个runnable对象,该对象也实现了run()方法。该thread对象调用start()方法后,会执行该对象重写的run()方法,其输出结果也就是run of thread,输出完后,run()方法返回,该线程对象的生命周期也就结束了。

在第二个代码段 2 中,同样也重写了thread的run()方法,同时传入了一个runnable对象,实现了run()方法。唯一不同的是,在thread重写的run方法中,在打印输出后,还执行了super.run(),这就有意思了。

首先,该线程启动运行后,执行其重写的run()方法,输出run of thread。

接下来调用super.run(),也就是调用超类的run()方法,而该超类的run()方法,也就是jdk定义的thread类的run(),其执行如上代码段 3 所示;显然target不为空,这时候会调用该对象的run()方法,会输出run of runnable.。

如果,上面的thread并未重写run()方法,那么,执行的结果还是一样。首先会执行该thread的run()方法,因为此时并未重写该方法,所以还是会调用jdk定以的run()方法,也就是上面的代码段 3,在该代码段中会判断target是否为空,显然不是,所以会调用runnable对象实现的run()方法。

总结:对于thread(runnable target …),不管传入的target是否为空,首先都会执行thread自己的run()方法。如果重写了该方法且该方法中没有super.run(),那么是永远不会调用runnable实现的run()方法;如果没有重写该方法,则会去判断target是否为空,以此来决定调用target实现的run()方法;如果重写了该方法,且该方法中有super.run(),在执行完该语句之前的所有代码后,会判断target是否为空,以此来决定调用target实现的run()方法,执行完后,接着执行该语句之后的代码。