92 第九天 魔乐java基础视频学习笔记Word文档格式.docx
- 文档编号:18955680
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:31
- 大小:1.37MB
92 第九天 魔乐java基础视频学习笔记Word文档格式.docx
《92 第九天 魔乐java基础视频学习笔记Word文档格式.docx》由会员分享,可在线阅读,更多相关《92 第九天 魔乐java基础视频学习笔记Word文档格式.docx(31页珍藏版)》请在冰豆网上搜索。
3.2.1、继承Thread类实现多线程
java.lang.Thread是一个负责线程操作的类,任何的类只需要继承了Thread类就可以成为一个线程的主类,但是既然是主类必须有它的使用方法,而线程启动的主方法是需要覆写Thread类中的run()方法才可以。
范例:
定义一个线程的主体类
classMyThreadextendsThread{//线程的主体类
privateStringtitle;
publicMyThread(Stringtitle){
this.title=title;
}
publicvoidrun(){//线程的主方法
for(intx=0;
x<
50;
x++){
System.out.println(this.title+"
运行,x="
+x);
}
}
现在按照道理来讲,已经出现了线程类,并且里面也存在了相应的操作方法,那么就应该产生对象并调用里面的方法,自然下面编写出下面程序。
publicclassTestDemo{
publicstaticvoidmain(Stringargs[])throwsException{
MyThreadmt1=newMyThread("
线程A"
);
MyThreadmt2=newMyThread("
线程B"
MyThreadmt3=newMyThread("
线程C"
mt1.run();
mt2.run();
mt3.run();
但是以上的操作实话而言并没有真正的启动多线程,因为多个线程彼此之间的执行一定是交替的方式运行,而此时是顺序执行,即:
每一个对象的代码执行完之后才向下继续执行。
如果要想在程序之中真正的启动多线程,必须依靠Thread类的一个方法:
publicvoidstart(),表示真正的启动多线程,调用此方法后会间接调用run()方法。
mt1.start();
mt2.start();
mt3.start();
此时可以发现,多个线程之间彼此交替执行,但是每次的执行结果肯定是不一样的,通过以上的代码就可以得出结论:
要想启动线程必须依靠Thread类的start()方法执行,线程启动之后会默认调用了run()方法。
疑问?
为什么线程启动的时候必须调用start()而不是直接调用run()?
发现调用了start()之后,实际上它执行的还是覆写后的run()方法,那为什么不直接调用run()方法呢?
那么咱们为了解释此问题,下面打开Thread类的源代码,观察以下start()方法的定义。
publicsynchronizedvoidstart(){
if(threadStatus!
=0)
thrownewIllegalThreadStateException();
group.add(this);
booleanstarted=false;
try{
start0();
started=true;
}finally{
try{
if(!
started){
group.threadStartFailed(this);
}
}catch(Throwableignore){
privatenativevoidstart0();
打开此方法的实现代码首先可以发现方法会抛出一个“IllegalThreadStateException”异常。
按照之前所学习的方式来讲,如果一个方法之中使用了throw抛出了一个异常对象,那么这个异常应该使用try…catch捕获,或者是方法的声明上使用throws抛出,但是这块都没有,因为这个异常是属于运行时异常(RuntimeException)的子类。
Java.lang.Object
|.java.lang.Throwable
|.java.lang.Exception
|.java.lang.Runtime.Exception
|.java.lang.llegalArgumentException
|.java.lang.IllegalThreadStateException
当一个线程对象被重复启动之后会抛出一个异常,即:
一个线程对象只能启动唯一的一次,在start()方法之中有一个最为关键的部分就是start0()方法,而且这个方法上使用了一个native关键字的定义。
native关键字指的是Java本地接口调用(JavaNativeInterface),即:
是使用Java调用本机操作系统的函数功能完成一些特殊的操作,而这样的代码开发在Java之中几乎很少出现,因为Java的最大特点是可移植性,如果一个程序只能在固定的操作系统上使用,那么可移植性就将彻底的丧失,所以,此操作一般只作为兴趣使用。
多线程的实现一定需要操作系统的支持,那么以上的start0()方法实际上就和抽象方法很类似,没有方法体,而这个方法体交给JVM去实现,即:
在windows下的JVM可能使用A方法实现了start0(),而在linux下的JVM可能使用了B方法实现了start0(),但是在调用的时候并不会关心具体是何种方式实现了start0()方法,只会关心最终的操作结果,交给JVM去匹配了不同的操作系统。
所以在多线程操作之中,使用start()方法启动多线程的操作是需要进行操作系统函数调用的。
3.2.2、实现Runnable接口实现多线程
使用Thread类的确是可以方便的进行多线程的实现,但是这种方式最大的缺点就是单继承的问题,为此,在java之中也可以利用Runnable接口来实现多线程,而这个接口的定义如下:
PublicinterfaceRunnable{
publicvoidrun();
分享:
如何区分新老接口?
在JDK之中,由于其发展的时间较长,那么会出现一些新的接口和老的接口,这两者有一个最大的明显特征:
所有最早提供的接口方法里面都不加上public,所有的新接口里面都有public。
通过Runnable接口实现多线程
classMyThreadimplementsRunnable{//线程的主体类
publicvoidrun(){
这个时间和之前的继承Thread类区别不大,但是唯一的好处就是避免了单继承局限,不过现在问题也就来了。
刚刚解释过,如果要想启动多线程依靠Thread类的start()方法完成,之前继承Thread类的时候可以将此方法直接继承过来使用,但是现在实现的是Runnable接口,没有这个方法可以继承了,为了解决这个问题,还是需要依靠Thread类完成,在Thread类中定义了一个构造方法:
publicThread(Runnabletarget),接收Runnable接口对象。
利用Thread类启动多线程
newThread(mt1).start();
newThread(mt2).start();
newThread(mt3).start();
这个时候就实现了多线程的启动,而且没有了单继承局限。
3.2.3、Thread类和Runnable接口实现多线程的区别(面试题)
现在Thread类和Runnable接口都可以作为同一功能的方式来是实现多线程,那么这两者如果从Java的实际开发而言,肯定使用Runnable接口,可以有效的避免单继承的局限,那么除了这些之外,这两种方式是否还有其他联系呢?
为了解释这两种方式的联系,下面可以打开Thread类的定义。
publicclassThreadextendsObjectimplementsRunnable
发现Thread类也是Runnable接口的子类,而如果真的是这样,那么之前程序的结构就变为了以下的形式。
这个时间所表现出来的代码模式非常类似于代理设计模式,但是它并不是严格意义上代码设计模式,因为从严格来讲代理设计模式之中,代理主题所能够使用的方法依然是接口中定义的run()方法,而此处代理主题调用的是start()方法,所以只能够说形式上类似于代理设计模式,但是本质上还是有差别的。
但是除了以上的联系之外,对于Runnable和Thread类还有一个不太好区分的区别:
使用Runnable接口可以更加方便的表示出数据共享的概念。
通过继承Thread类实现卖票程序
packagecn.mldn.demo;
privateintticket=5;
//一共5张票
if(this.ticket>
0){
System.out.println("
卖票,ticket="
+this.ticket--);
MyThreadmt1=newMyThread();
MyThreadmt2=newMyThread();
MyThreadmt3=newMyThread();
现在的结果是一共买出了15张票,等于是每一个程序对象各自卖各自的5张票,这个时候的内存关系图如下:
利用Runnable来实现多线程
MyThreadmt=newMyThread();
newThread(mt).start();
现在使用继承Thread类也可以实现同样的功能。
面试题:
请解释多线程的两种实现方式及区别?
分别编写程序以验证两种实现方式。
·
多线程的两种实现方式都需要一个线程的主类,而这个类可以实现Runnable接口或继承Thread类,不管使用何种方式都必须在子类之中覆写run(),此方法为线程的主方法;
Thread类是Runnable接口的子类,而且使用Runnable接口可以避免单继承局限,以及更加方便的实现数据共享的概念。
·
程序实现
Runnable接口:
Thread类:
classMyThreadimplementsRunnable{privateintticket=5;
//线程操作方法
classMyThreadextendsThread{
MyThreadmt=newMyThread();
mt.start();
3.2.4、线程的操作状态(了解)
每一个线程对象实际上都有属于自己的运行状态,那么下面分别说明线程的每种运行状态的特点:
1、所有的线程对象都必须通过关键字new进行创建;
2、线程如果要进行启动则一定会调用Thread类的start()方法,但是代码可能会分先后顺序:
newThread(mt).start();
以上是启动了三个线程,虽然在代码上有先后调用start()方法的顺序,可是对于JVM而言,都表示着所有的线程将同时进入到就绪状态,等待执行。
3、进入到就绪状态之后,将等待CPU进行资源的抢占,抢占到了资源之后,线程会进行到运行状态,开始执行run()方法体之中所定义的代码;
4、每一个线程执行run()方法到一定的时间的时候会让出CPU资源,进入到阻塞状态,而后重新回到就绪状态等待下次资源调度并继续执行run(0方法中的代码;
5、如果全部方法执行完毕之后,将进入到线程的终止状态,并且不会再进入到就绪状态,直接结束。
3.3、线程的主要操作方法(理解)
线程对象的也是可以进行若干种操作的,而且所有的线程操作方法都在Thread类中定义,如果要想学习完整的方法,可以参考本人的书《java开发实战经典》,但是下面只讲解核心的几个方法。
3.3.1、线程的命名和取得
线程本身是属于不可见的运行状态的,即:
每次操作的时候是无法预料的。
所以如果要想在程序之中操作线程,唯一依靠的就是线程名称,而要想取得和设置线程的名称可以使用如下的方法:
构造方法:
publicThread(Runnabeltarget,Stringname)
设置名字:
publicfinalvoidsetName(Stringname)
取得名字:
publicfinalStringgetName()。
但是由于线程的状态不确定,所以每次可以操作的都是正在执行run()方法的线程,那么取得当前线程对象的方法:
publicstaticThreadcurrentThread()。
线程的命名和取得
packagecn.mldn.demo;
classMyThreadimplementsRunnable{//线程的主体类
System.out.println(Thread.currentThread().getName());
publicclassTestDemo{
publicstaticvoidmain(String[]args)throwsException{
//Thread-0
//Thread-1
//Thread-2
newThread(mt,"
).start();
//线程A
//线程B
如果说现在为线程设置名字的话,那么会使用用户定义的名字,而如果没有设置线程名称,会自动的为其分配一个名称,这一点操作和之前讲解的static命名类似。
观察如下代码
线程"
//启动线程,并设置名字,线程
mt.run();
//在主方法中,直接调用类的run()方法,main
通过如上的程序可以发现,原来一个主方法也是一个线程,但是有一个问题出现了,现在一直是讲解了多线程,但是线程一定要依附于进程,进程在哪里啊?
每一次使用java命令执行一个类的时候就表示启动了一个JVM的进程,而主方法是在这个进程上的一个线程而已。
问题:
一个JVM进程启动的时候至少启动几个线程呢?
两个线程:
main、gc
3.3.2、线程的休眠
线程的休眠指的是让程序的执行速度变慢一些,方法:
publicstaticvoidsleep(longmillis)throwsInterruptedException,设置的休眠单位是毫秒。
x<
100;
x++){
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
System.out.println(Thread.currentThread().getName()+"
,x="
+x);
线程D"
线程E"
这
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 92 第九天 魔乐java基础视频学习笔记 九天 魔乐 java 基础 视频 学习 笔记