《多线程与Socketliyue-stu.pptx》由会员分享,可在线阅读,更多相关《多线程与Socketliyue-stu.pptx(58页珍藏版)》请在三一办公上搜索。
1、1,class Super public int field=0;public int getField()return field;class Sub extends Super public int field=1;public int getField()return field;public int getSuperField()return super.field;public class FieldAccess public static void main(String args)Super sup=new Sub();/Upcast System.out.println(sup
2、.field=+sup.field+,sup.getField()=+sup.getField();Sub sub=new Sub();System.out.println(sub.field=+sub.field+,sub.getField()=+sub.getField()+,sub.getSuperField()=+sub.getSuperField();,sup.field=0,sup.getField()=1sub.field=1,sub.getField()=1,sub.getSuperField()=0,2,class FatherClass protected class Gi
3、ft public Gift()System.out.println(FatherClass.Gift();public void f()System.out.println(FatherClass.Gift.f();private Gift y=new Gift();public FatherClass()System.out.println(New FatherClass();public void insertGift(Gift yy)y=yy;public void g()y.f();public class SonClass extends FatherClass public cl
4、ass Gift extends FatherClass.Gift public Gift()System.out.println(SonClass.Gift();public void f()System.out.println(SonClass.Gift.f();public SonClass()insertGift(new Gift();public static void main(String args)FatherClass e2=new SonClass();e2.g();,FatherClass.Gift()New FatherClass()FatherClass.Gift()
5、SonClass.Gift()SonClass.Gift.f(),1,彼此独立,“同时”工作,线程与工作人员,什么是线程?,线程是一个程序(进程)内部的顺序控制流,必须依赖于进程中执行,一个进程可实现多个线程,同时完成不同的任务。多线程意味着一个程序的多行语句同时执行,并不是多次启动同一个程序。不同进程的代码、内部数据和状态都是独立的,而进程中的多线程是共享同一内存空间和同一系统资源,可能会相互影响。,线程两种实现方法:继承Thread类和继承Runnable接口,用继承方式创建线程,很简单,只需要继承类,并覆盖Thread类的run方法。Thread类有两个很重要的方法:run方法和star
6、t方法Run方法是加入需要执行代码的地方,是线程体,但不能直接调用,需要通过调用start方法启动线程(初始化相关资源)并运行run方法。,但是因为java不支持多继承,如果已经继承了其他类就无法在继承Thread类了。这样就要通过实现接口来创建线程了。,用实现接口方式创建线程,通过实现接口来创建多线程,该接口只有一个run方法,重写就好了。,但是,必须要调用Thread类构造方法public Thread(Runnable target)来创建Thread类的实例才能提供对多线程的支持。,下面是例子:,public class ThreadSynTest implements Runnabl
7、eprivate int num=10;public void doit()if(num0)try Thread.sleep(1000);catch(InterruptedException e)/TODO Auto-generated catch blocke.printStackTrace();System.out.println(tickets+-num);,Overridepublic void run()/重写run方法/TODO Auto-generated method stubwhile(true)doit();public static void main(String ar
8、gs)ThreadSynTest t=new ThreadSynTest();Thread a=new Thread(t);/新建线程Thread b=new Thread(t);Thread c=new Thread(t);Thread d=new Thread(t);a.start();/执行线程b.start();c.start();d.start();,tickets9tickets8tickets9tickets7tickets5tickets6tickets4tickets3tickets2tickets1tickets0tickets-1tickets-2,线程很简单,就是一个在
9、后台偷偷运行的“小(副)程序”,它的run()方法相当于主程序的main()方法,只不过要调用start()来启动它,也可以用一些指令将它暂停或者继续运行。其实我们天天都在接触线程,只不过我们的程序都是单线程(main方法)。新建一个线程并start()它,就相当于打开了一个新程序。多个线程一般平等地交叉运行,因为时间很短,故可以认为是同时运行。,想象一下,现在我们的程序是模拟银行的运行。如果只有一个工作人员负责接待成百上千名客户,并为他们办理业务,可不可行?当然不行,除非你的银行无论在什么时候都最多只有一位客户光临。现在有这样一个策略:假设员工休息室里有很多业务员在休息,当他们接到前台接待的
10、通知,就找一个业务员出去为客户办理业务,办理完了就回来休息。显然前台只要一个就够了,而柜台业务员则需要很多。,线程,简单来讲,是这样的单线程 多进程 多线程一个人对一个帖子 十个人对十个帖子一个人对十个帖子,创建线程,可以1.继承Thread类,重写run()方法,使用start()方法启动线程。class huaji extends Thread.public void run()水贴;.public static void main(String args)huaji xiaohuaji;xiaohuaji.start();,继承Thread类,以创建多线程,run()方法中说明这个线程要
11、执行什么(但不能直接调用,需要通过调用start方法启动线程(初始化相关资源)并运行run方法。),创建一个线程并执行run()里面的内容,2.实现Runnable接口中的run()方法,并通过Thread的构造方法public Thread(Runnable target)创建Thread实例class huaji implements Runnbale.public void run()水贴;.public static void main(String args)new Thread(new huaji).start();,创建一个Thread对象并执行其start()方法,2,接待客户
12、,呼唤柜台业务员,ServerSocket与前台,socket(摘自百科,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket,通常也称作套接字,用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。课本中的Socket例子包含一个服务端和客户端。服务端通过监听某个端口,等待客户端的连接;客户端通过已知服务端的ip地址以及开放端口,连接到指定服务端。它们之间通过流的形式进行信息的交流。即把创建对方为自己的一个Socket实例,并通过输入和输出两个流通信。也就是说,现阶段我们要写好Socket,就要掌握Socket的连接以及
13、流的使用。后续代码参考课本,PS:其实服务端和客户端的区别在于服务端相对固定,客户端通过服务端的信息来找到他,开始交流。相当于楼主发了个帖子,大家进去批判他,而不是楼主去找大家谈人生。在交流方式上,是相同的。,一、简单理解Socket,(1)Socket是什么?socket=套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。-来自网络 个人理解 就是一条数据线的作用(不用想那么复杂),个人理解,服务器,客户端,创建并提供端口,链接上IP地址,再接端口,BufferedRead流(读入数据),PrintWr
14、iter流(发送数据),简单来说:,可以把socket想象为以下过程:服务器=房子 端口=房子里的插座 客户端=手机现在要把手机连上插座充电,那么你首先得走进房子(连接上服务器IP地址),再找到插座(端口),同时连接手机(客户端)和插座(端口)需要数据线(socket)作为中介,这样两边才能进行正常的数据交换。,PS:,同时前面解释了一个问题:怎样判别连接上的端口就是想要连接的服务器的?类比一下类的封装特性,可以把端口看做封装在服务器中的成员,要想连接上服务器端口,首先得获取入口(服务器地址),然后才能通过IP查询到服务器的端口位置,避免出现多个服务器之间共用端口的情况(不同服务器IP地址是独
15、一无二的).,(3)代码部分解释,服务器端+客户端:ServerSocket s=new ServerSocket(PORT)利用ServerSocket类创建端口s对象,用于接收客户端数据以及提供端口Socket socket=s.accept()利用Socket类创建socket对象接收数据InetAddress addr=InetAddress.getByName(null):如果向getByName()传递一个null(空)值,就默认为使用localhost。我们用InetAddress对特定的机器进行索引,而且必须在进行进一步的操作之前得到这个InetAddress(互联网地址)。s
16、ocket.close()+s.close():finally中关闭对象,PrintWriter out=new PrintWriter(new 创建打印输出对象BufferedWriter(new 缓冲区数据流输出OutputStreamWriter(socket.getOutputStream(),true);数据输出流 socket对象获取向外输出数据out.println():直接输出并发送括号中的数据,BufferedReader in=new BufferedReader(new 创建缓冲区数据流读取对象 InputStreamReader(socket.getInputStrea
17、m()输入数据流读取 socket获取输入数据String str=in.readln():整行读入发送来的数据,以上是socket简单框架的代码,写的时候再:import java.io.*;import.*;加上:trycatchfinally即可至多:extends Thread,用run实现多线程个人代码都是在此基础上加上框架和程序功能实现代码而已,待扩展的地方很多。,什么是Socket?,端口:一般而言,一台计算机只有单一的连接到网络的物理连接(Phy Connection),所有的数据都通过此连接对内对外送达特定的计算机,这就是端口。但网络程序设计中的端口并非真实的物理存在,而是被
18、规定为0-65535之间的整数。,网络程序设计中的套接字(Socket)用于将程序和端口连接起来。,套接字分为(服务器程序)ServerSocket和(客户机程序)Socket,其实,Socket肯定用于创建某种Reader以及/或Writer(或者InputStream和/或OutputStream)对象,这是运用Socket的唯一方式。,ServerSocket,服务器套接字ServerSocket主要功能是等待来自网络上的“请求”,一般使用构造方法ServerSocket(int port)来绑定到指定接口等待连接。,ServerSocket server=new ServerSocke
19、t(8080);,调用accept()方法会返回一个和客户端Socket对象相连接的Socket对象。,Socket socket=server.accept();,客户端Socket,构造方法一般为Socket(String host,int port),前一个参数是要连接的IP地址,后一个是要连接的端口。,client=new Socket(InetAddress.getByName(null),8080);,多线程Socket例子,服务器端:,import.*;import java.io.*;class Mult extends Thread/用继承方式实现多线程private Soc
20、ket socket;/输入流和输出流private BufferedReader in;private PrintWriter out;public Mult(Socket s)throws IOExceptionsocket=s;/由Socket得到输入流和输出流实例对象in=new BufferedReader(new InputStreamReader(socket.getInputStream();out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),true);s
21、tart();/开启线程,public void run()/重写run方法,线程体trywhile(true)/无限循环,读入数据String str=in.readLine();if(str.equals(END)/跳出循环条件break;System.out.println(Echoing:+str);out.println(str);/数据输出System.out.println(closing.);catch(IOException e)finallytry/如有异常,关闭socketsocket.close();catch(IOException e),续:,public clas
22、s ServerSocketMultstatic final int PORT=8080;/端口号public static void main(String args)ServerSocket s=new ServerSocket(PORT);/创建服务器套接字System.out.println(Server Started);trywhile(true)/*无限循环接收客户套接字连接请求*/Socket socket=s.accept();try/每接受一次请求创建一个新的Mult对象实例,运行一个新的线程new Mult(socket);catch(IOException e)sock
23、et.close();finally/最后关闭服务器套接字s.close();,续:,Socket的连接(参考课本,简单来说,服务端程序(楼主):public static final int PORT=8080;/选定了一个端口.ServerSocket s=new ServerSocket(PORT);/通过该端口创建了服务端实例(帖子),服务端程序(楼主):Socket socket=s.accept();/此时,通过accept()方法等待回帖的人,并创建一个客户端的实例。,客户端:Socket socket=new Socket(addr,PORT);通过addr和PORT把服务端创
24、建为一个Socket实例,其中addr为服务端ip地址,PORT为服务端开放端口。,已经建立联系,可以互喷了(x,Socket的流(参考课本,简单来说现在服务端和客户端都分别把对方创建为了一个Socket对象,然后声明了两个流in=new BufferedReader(new InputStreamReader(socket.getInputStream();out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),true);这里 in 是对方的输出流,out是对方的读入流,服
25、务端,客户端,out.println(内容);,out.println(内容);,in.readLine();,in.readLine();,Socket,Socket能实现的只有流的传输,本质上只是信息的交换,那么这些信息能干什么,就决定了这个程序的用途。至于多线程服务端里大家有没有觉得课本里run()里面的东西很熟悉,没错简单来讲只是把流的操作写了进去。正如前面所说,run()方法里面是线程所要实现的功能,那么在这里对于架设好的服务端,需要每个线程重复操作的只是对每个接入客户端的流的处理。与之对应的客户端在多线程里就是把每个线程客户端所要对流的处理放进run()里面即可。,Socket,简
26、单来说,课本里多线程socket是这么一个情况。其实,一般服务端写成多线程就ok了吧吧。,服务端,客户端,前台,也就是接待员的工作很简单,很机械。看见客户来了,就说“欢迎光临,请您到*柜台办理业务。”然后打电话到员工休息室,叫一名业务员出来负责处理该客户的业务。他大多数的时间都用在等待新客户的光临上面,相当于ServerSocket的accept()方法。,如果你要到银行办理业务,你是不是得要先知道银行在哪?比如*区*街道。这个银行的地址相当于ServerSocket的IP地址。但是知道哪个街道还不行,因为整条街这么多店铺,有时还不止一家银行,所以我还要知道几号几零几才行。这个就相当于端口号。
27、(IP负责找到运行服务器程序的电脑,端口号负责找到这台电脑哪个程序才是服务器程序),知道了地址,我们只需要call一辆出租车让他送我到指定地点就行了,我们完全不用管具体要怎么走。这相当于客户端程序中Socket s=new Socket(IP,Port);到达银行后,等待已久的前台接待马上会招呼你,并让你到指定柜台办理业务了。,办理业务的方式就很简单啦,你说我做,你问我答。客户不需要清楚业务员是怎样操作电脑把钱存进去的。业务员不能自作主张,客户说啥你就做啥,如果需要更多信息,问一下客户就是。这里的说相当于流的Write()方法,听相当于Read()方法。,一个人的耳朵和嘴巴肯定是独立的啦,同时
28、执行完全不同的任务。不可能因为耳朵要准备接受信息,而导致嘴巴没法说话,大脑无法思考。(试想一下单线程时的Read()方法,你就懂我在说啥)所以客户端需要一个专门听(和准备听)对方说话的线程(我称它为耳朵线程)。一般柜台业务员就只有耳朵线程,因为他不能有创造,无需有思考,只用听用户的话,完成相应指令就好。(符合网络通讯的“请求-响应”模型。,建立与连接,服务器任务:等候建立一个连接ServerSocket s,然后就此连接创建Socket对象,并调用accept(),直到某个客户尝试请求连接然后创建一个IS和OS,读入与反馈信息,客户程序获得本地主机IP地址addr后建立一个Socket对象,并
29、请求与服务器连接,正确建立与连接结果:,客户未创建且未请求连接:,正确:accept()接收到连接请求,成功输出connection accepted未连接:accept()一直在等待连接失败:Socket不再存在,调用s.closet();,服务器与客户的沟通交流,服务器的in读取客户的out,服务器的out反馈给客户in;客户的in读取服务器的out,客户的out发送给服务器in,客户不读不发送:服务器读取反馈失败,关闭连接,*若服务器没有设置终止跳出,则会一直等待读取,客户只读不发送:服务器一直在等待信息,客户能读取服务器发送的信息,客户只发送不读取:客户发送信息后无其余动作则退出服务器
30、若有终止跳出则抛出异常,否则一直等待读取,服务器不读不反馈:服务器一直监测客户,服务器只读不反馈:服务器一直读取,客户端也一直等待反馈,服务器只反馈不读:服务器一直监测客户,客户能接收服务器信息,/Server_Socket.javapublic static void main(String args)throws IOException ServerSocket s=new ServerSocket(PORT);/创建ServerSocket。如果创建失败会自动退出程序System.out.println(Started:+s);try/用try-finally块保证无论以什么方式结束,S
31、erverSocket都会正确关闭Socket socket=s.accept();/调用accept()方法,暂时陷入停顿状态,直到有某个客户尝试同它建立连接,建立连接后会返回一个Socket对象try System.out.println(Connection accepted:+socket);BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream();/创建输入流,读取socket输入的文本内容PrintWriter out=new PrintWriter(new Buffered
32、Writer(new OutputStreamWriter(socket.getOutputStream(),true);/创建输出流,准备向socket输出文本内容,每次println结束后自动刷新输出缓冲区,服务端,客户端,accept(),创建链接,关闭,抛出异常,断开链接,while(true)String str=in.readLine();/读取socket输入文本的一整行,直到遇到ENDif(str.equals(END)break;System.out.println(Echoing:+str);/在服务器端输出收到的字符串out.println(str+str+haha);/
33、向socket客户端输出字符串 finally System.out.println(closing.);socket.close();/关闭与客户端的链接,readLine抛出异常。finally s.close();/关闭服务器端,服务端,客户端,输入流,输出流,输入流,输出流,/Client_Socket.javapublic class Client_Socket public static void main(String args)throws IOException InetAddress addr=InetAddress.getByName(null);/获取主机名和IP号Sy
34、stem.out.println(addr=+addr);/创建Socket,用IP地址和端口号作为参数 Socket socket=new Socket(addr,Server_Socket.PORT);try/用try-finally块保证无论以什么方式结束,socket都会正确关闭System.out.println(socket=+socket);BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream();/创建读取流,准备读取客户端Server_socket输入的文本内容Prin
35、tWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),true);/创建输出流,准备向客户端输出文本内容,/循环向服务器端输出,并读取服务端发来的数据for(int i=0;i 10;i+)out.println(www+i);String str=in.readLine();System.out.println(str);out.println(END);finally System.out.println(closing.);socket.close();
36、/关闭客户端socket,readLine抛出异常,多线程,服务端,客户端,accept(),创建线程,客户端,客户端,客户端,客户端,创建线程,创建线程,创建线程,创建线程,客户端,创建链接,关闭,抛出异常,断开链接,/Mult.java继承Thread,作为单个线程执行的内容,内容和单线程的服务器端相似/构造器中用参数绑定链接的客户端socket=s;/start()开始执行run()方法里面的内容,run()方法里的内容和单线程的服务器端相似start();,/ServerSoketMult.javapublic static void main(String args)throws I
37、OException ServerSocket s=new ServerSocket(PORT);System.out.println(Server Started);try while(true)/每次有客户端连接的时候,都会生成一个socket对象,开一个线程进行与单线程客户端相同的工作Socket socket=s.accept();try new Mult(socket);catch(IOException e)socket.close();finally s.close();,JAVA网络模型,服务单个的客户端的。就直接服务器端ServerSocket 创建port ServerSocket serverSocket=new ServerSocket(8080);然后Socket socket=serverSocket.accept();等待Client的Socket连接。然后Client连接Server端指定的port;Socket socket=new Socket(“localhost”,8080);,谢 谢,虽然有点扯,但编程就是这样,