您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 公司方案 > 笔记--Java8编程开发入门
1Java多线程实现线程与进程Java是一门为数不多的支持多线程编程的语言。进程?在操作系统的定义中,进程指的是一次程序的完整运行,这个运行的过程之中内存、处理器、IO等资源操作都要为这个进程服务。在最早的dos系统的时代,有一个特点:如果你电脑病毒发作了,那么你电脑几乎就不能动了。因为所有的资源都被病毒软件所占用,其他的程序无法抢占资源。但是到了后来Windows时代,这一情况发生了改变,电脑即使有病毒,电脑也可以运行(就是慢点)。Windows属于多进程的操作系统。但是有一个问题出现了:每一个进程都需要有资源的支持,那么多个进程怎么去分配资源呢?在同一个时间段上,会有多个进程轮流去抢占资源。但是在某一个时间点上只能有一个进程。线程?线程是在进程的基础上进一步划分的结果,即:一个进程上可以同时创建多个线程。线程是比进程更快的处理单元,而且所占的资源也小。那么多线程的应用也是性能最高的应用。总结:线程的存在离不开进程。进程如果消失后,线程一定会消失。反之线程消失了进程未必会消失。Thread类实现掌握java中3种多线程的实现方式(JDK1.5之后增加了第3种)。如果想在java中实现多线程,有两种途径:1.继承Thread类;2.实现Runable接口(Callable接口)。Thread类是一个支持多线程的功能类,只要有一个类继承了Thread那么它就是一个多线程的类。ClassMyThreadextendsThread{}所有程序的起点是main()方法。但是所有线程也有自己的起点,即:run()方法。在多线程的每个主体类之中都必须覆写Thread类中所提供的run()方法。publicvoidrun(){}这个方法没有返回值,那么也就表示线程一旦开始那么就要一直执行,不能够返回内容。classMyThreadextendsThread{privateStringname;//定义属性publicMyThread(Stringname){//定义构造方法this.name=name;}@Overridepublicvoidrun(){//覆写run方法,作为线程的主体方法for(intx=0;x200;x++){System.out.println(this.name+-------+x);}}}本线程类的功能是进行循环的输出操作。所有的线程跟进程一样的,都必须轮流抢占资源。2所以多线程的执行应该是多个线程彼此交替执行,也就是说如果直接调用了run()方法,那么就不能够启动多线程,多线程启动的唯一方法就是Thread类中的start()方法:publicvoidstart(),调用此方法执行的方法体是run()方法定义的。packagecn.mldn.util;classMyThreadextendsThread{privateStringname;//定义属性publicMyThread(Stringname){//定义构造方法this.name=name;}@Overridepublicvoidrun(){//覆写run方法,作为线程的主体方法for(intx=0;x100;x++){System.out.println(this.name+-------+x);}}}publicclassTestDemo{publicstaticvoidmain(Stringargs[]){MyThreadmt1=newMyThread(线程A);MyThreadmt2=newMyThread(线程B);MyThreadmt3=newMyThread(线程C);mt1.start();mt2.start();mt3.start();}}此时每一个线程对象交替执行。疑问?为什么多线程启动不是调用run(),而必须调用start()?Thread的start()方法不仅仅要启动多线程的执行代码,还要去根据不同的操作系统进行资源的分配。Runnable接口实现虽然Thread类可以实现多线程的主体类定义,但是它有一个问题,java具有单继承局限,正因为如此,在任何情况下针对于类的继承都应该是回避的问题,那么多线程也一样,为了解决单继承的限制,在java里面专门提供了Runable接口:@FunctionalInterfacepublicinterfaceRunnable{//函数式接口,特征是一个接口只能有一个方法publicvoidrun();}在接口里面任何的方法都是public定义的权限,不存在默认的权限。那么只需要让一个类实现Runnable接口,并且也需要覆写run()方法。与继承Thread类相比,此时的MyThread类在结构上是没有区别的,但是有一点是有严重区别的:如果此时继承了Thread类,那么可以直接继承start()方法;但如果实现的是Runnable接口,并没有start()方法可以被继承。classMyThreadimplementsRunnable{privateStringname;//定义属性3publicMyThread(Stringname){//定义构造方法this.name=name;}@Overridepublicvoidrun(){//覆写run方法,作为线程的主体方法for(intx=0;x100;x++){System.out.println(this.name+-------+x);}}}不管何种情况下,如果要想启动多线程,一定依靠Thread类完成,在Thread类里定义有如下的构造方法:publicThread(Runnabletarget),接收的是Runnable接口对象;范例:packagecn.mldn.util;classMyThreadimplementsRunnable{privateStringname;//定义属性publicMyThread(Stringname){//定义构造方法this.name=name;}@Overridepublicvoidrun(){//覆写run方法,作为线程的主体方法for(intx=0;x200;x++){System.out.println(this.name+-------+x);}}}publicclassTestDemo{publicstaticvoidmain(Stringargs[]){MyThreadmt1=newMyThread(线程A);MyThreadmt2=newMyThread(线程B);MyThreadmt3=newMyThread(线程C);Threadm1=newThread(mt1);Threadm2=newThread(mt2);Threadm3=newThread(mt3);m1.start();m2.start();m3.start();}}此时就避免了单继承局限,那么也就是说在实际工作中使用接口是最合适的。两种实现方式的区别(面试题)通过讲解已经清楚多线程两种实现方式,这两种方式有哪些区别?首先我们要明确的是使用Runnable接口与Thread相比,解决了单继承局限,所以不管后面的区别与联系,至少这一点就已经下了死定义。如果要使用,一定使用Runnable接口。4观察Thread类定义:publicclassThreadextendsObjectimplementsRunnable发现Thread类实现了Runnable接口。此时整个的定义结构非常像代理设计模式,如果是代理设计模式,客户端调用的代理类的方法应该是接口里提供的方法,那么也应该是run()才对。除了以上的联系之外,还有一点:使用Runnable接口可以比Thread类更好的描述出数据共享这一概念。此时的数据共享指的是多个线程访问同一资源的操作。范例:观察代码Thread实现(每一个线程对象都必须通过start()启动)packagecn.mldn.util;classMyThreadextendsThread{privateintticket=10;//定义属性@Overridepublicvoidrun(){//覆写run方法,作为线程的主体方法for(intx=0;x100;x++){if(this.ticket0){System.out.println(卖票,ticket=+this.ticket--);}}}}publicclassTestDemo{publicstaticvoidmain(Stringargs[]){//由于Mythread类有start()方法,所以每一个MyThread类就是一个线程对象,可以直接启动MyThreadmt1=newMyThread();MyThreadmt2=newMyThread();MyThreadmt3=newMyThread();mt1.start();5mt2.start();mt3.start();}}本程序声明了3个MyThread类对象,并且分别调用了3次start()方法启动线程对象。结果是每一个线程对象都在卖各自的票。此时并不存在数据共享。范例:利用Runnable实现packagecn.mldn.util;classMyThreadimplementsRunnable{privateintticket=10;//定义属性@Overridepublicvoidrun(){//覆写run方法,作为线程的主体方法for(intx=0;x100;x++){if(this.ticket0){System.out.println(卖票,ticket=+this.ticket--);}}}}publicclassTestDemo{publicstaticvoidmain(Stringargs[]){MyThreadmt1=newMyThread();newThread(mt1).start();newThread(mt1).start();newThread(mt1).start();}}此时也属于3个线程对象,唯一的区别是这3个线程对象都占用了同一个MyThread类的对象引用,也就是这3个线程对象都直接访问同一个数据资源。6面试题:请解释Thread类与Runnable接口实现多线程的区别?(请解释多线程两种实现方式的区别?)Thread类是Runnable接口的子类,使用Runnable接口实现可以避免单继承局限;Runnable接口实现的多线程可以比Thread类实现的多线程更加清楚的描述数据共享的概念。请写出多线程两种实现操作?把Thread类继承的方式和Runnable接口实现的方式都写出来。Callable接口(理解)使用Runnable接口实现的多线程可以避免单继承局限,但是有一个问题,Runnable接口里面的run()方法不能返回操作结果。为了解决这个矛盾,提供了一个新的接口:java.util.concurrent.Callable接口。publicInterfaceCallableV{publicVcall()throwsException;}Call()方法完成线程的主体功能后可以返回一个结果,而这个结果的类型由Callable接口的泛型决定。范例:定义一个线程主体类importjava.util.concurrent.Callable;classMyThreadimplementsCallableString{privateintticket=10;//定义属性@OverridepublicStringcall()throwsException{for(intx=0;x100;x++){if(this.ticket0){System.out.println(卖票,ticket=+this.ticket--);}}return票已卖光!!!;7}}此时观察Thread类里面并没有直接支持Callable接口的多线程应用。从JDK1.5开始提供有java.util.concurrent.FutureTa
本文标题:笔记--Java8编程开发入门
链接地址:https://www.777doc.com/doc-3623413 .html