实验06多线程剖析.docx
《实验06多线程剖析.docx》由会员分享,可在线阅读,更多相关《实验06多线程剖析.docx(19页珍藏版)》请在冰点文库上搜索。
![实验06多线程剖析.docx](https://file1.bingdoc.com/fileroot1/2023-5/17/1ce2b58c-be8d-4434-a375-e1607ef47502/1ce2b58c-be8d-4434-a375-e1607ef475021.gif)
实验06多线程剖析
实验六TCPSocket中的多线程
一、本实验目的及要求:
1.理解进程和线程的概念;
2.掌握JAVA中多线程技术,实现方法(继承Thread类,或实现Runnable接口);
3.将多线程技术和TCPSocket结合,在TCPSocket中引用多线程技术,实现多用户实时通信;
4.实验报告内容应包括,本实验的第三、四、五部分的答案,以及第六部分的程序后要求。
二、基础知识
每个正在系统上运行的程序都是一个进程(process)。
每个进程包含一到多个线程(thread)。
进程也可能是整个程序或者是部分程序的动态执行。
线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。
也可以把它理解为代码运行的上下文。
所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。
Java对多线程的支持是非常强大的,他屏蔽掉了许多的技术细节,让我们可以轻松的开发多线程的应用程序。
Java里面有2个方法实现多线程,
1继承Thread类,比如
classMyThreadextendsThread{
publicvoidrun(){
//这里写上线程的内容
}
publicstaticvoidmain(String[]args){
//使用这个方法启动一个线程
newMyThread().start();
}
}
2实现Runnable接口,例如
classMyThreadimplementsRunnable{
publicvoidrun(){
//这里写上线程的内容
}
publicstaticvoidmain(String[]args){
//使用这个方法启动一个线程
newThread(newMyThread()).start();
}
}
一般鼓励使用第二种方法,因为Java里面只允许单一继承,但允许实现多个接口。
第二个方法更加灵活。
3、基础知识填空
1.程序的概念是(),进程的概念是(),线程的概念是()。
2.线程的两种实现方法,分别是继承()和实现()接口。
3.线程的四个状态分别是()、()、()和()。
Sleep是线程重要的方法其作用是()。
4.在自定义线程是,必须要要重写()方法,通过()启动线程对象。
5.为了避免多个线程共享一个资源而引起的冲突,在Java中提供了关键字()实现了资源锁,该关键字可以修饰方法也可以修饰程序段。
4、程序填空
1.采用继承Thread方法声明一个线程类
publicclassmyThreadextends(){//继承线程类
publicmyThread(){//构造方法中的参数
super(name);
}
publicvoid(){//线程中运行的方法
System.out.println("welcome");
}
publicstaticvoidmain(String[]args){
myThreadmyT=newmyThread("线程1");
myT.();//启动线程
}
}
2.采用实现Runnable接口方法声明一个线程类
publicclassmyThreadimplements(){
publicmyThread(Stringname){
(name);
}
publicvoid(){
System.out.println("welcome");
}
publicstaticvoidmain(String[]args){
myThreadmyT=newmyThread("线程1");
ThreadtMy=new(myT);
.start();
}
}
2多线程累计器
classSum{//共享资源,计数器count
intcount;//共享资源
publicintadd(){//同步锁
count=count+1;
System.out.println("add:
"+count);
returncount;
}
}
classSumThreadextendsThread{//定义线程
privateSumsd;
privateintsum=0;
publicSumThread(Stringname,Sumsd){
super(name);
this.sd=sd;
}
publicvoidrun(){//必需的重写
try{
for(inti=0;i<10;i++){
sum+=sd.add();
Thread.sleep();
}
Thread.sleep(1000);
}catch(Exceptione){}
System.out.println(getName()+"累加和:
"+sum);
}
publicintgetSum(){
returnsum;
}}
publicclassSumDemo{
publicstaticvoidmain(String[]args){
Sumsd=newSum();//代表共享资源的变量
SumThreadst1=newSumThread("线程1",sd);//创建完毕
SumThreadst2=newSumThread("线程2",);
SumThreadst3=newSumThread("线程3",sd);
st1.;//使线程运行
st2.start();st3.start();
st1.;st2.join();st3.join();
System.out.println("总和为:
"+(st1.getSum()+st2.getSum()+st3.getSum()));
}}
五、实验内容
1.多线程累加示例。
在本例中,实现1-30的累计,其中共享资源池为1-30的数字的递增,采用了同步锁synchronized。
classSum{//共享资源,计数器count
privateintcount;//共享资源
publicintadd(){
synchronized(this){//代码段1,共享锁,修饰程序段或者方法
count=count+1;
System.out.println("add:
"+count);
returncount;
}
}
}
classSumThreadimplementsRunnable{//定义线程
privateSumsd;
privateintsum=0;
privateint[]a=newint[10];
publicSumThread(Stringname,Sumsd){
super(name);
this.sd=sd;
}
publicvoidrun(){//必需的重写
try{
for(inti=0;i<10;i++){
a[i]=sd.add();
sum+=a[i];
Thread.sleep(100);
}
Thread.sleep(1000);
}catch(Exceptione){}
System.out.println(getName()+"累加和:
"+sum);
}
publicvoidshowData(){
System.out.print(getName()+"获得的数为");
for(inti=0;i<10;i++){
if(i%10==0)System.out.println();
System.out.print(a[i]+"+\t");
}
}
publicintgetSum(){
returnsum;
}
}
publicclassSumDemo{
publicstaticvoidmain(String[]args){
Sumsd=newSum();//代表共享资源的变量
SumThreads1=newSumThread("线程1",sd);//创建完毕
SumThreads2=newSumThread("线程2",sd);
SumThreads3=newSumThread("线程3",sd);
Threadst1=newThread(s1);
Threadst2=newThread(s2);
Threadst3=newThread(s3);
st1.setPriority(Thread.MAX_PRIORITY);//代码段2
st2.setPriority(10);
st3.setPriority
(1);
longbegin=System.currentTimeMillis();
st1.start();//使线程运行
st2.start();st3.start();
St1.join();st2.join();st3.join();
st1.showData();
st2.showData();
st3.showData();
System.out.println("总和为:
"+(st1.getSum()+st2.getSum()+st3.getSum()));
longend=System.currentTimeMillis();
System.out.println(“探测localhost的TCP端口,共耗时”+
(end-begin)+"毫秒");
}}
报告内容:
1.查看红色代码段1,观察保留synchronized和去掉,程序运行结果的变换;
2.查看红色代码段2,为每个线程设置不同优先级,查看各线程所得到的结果;
3.查找线程中方法join的作用;
4.修改程序为,可以实现1-10000的累计,看1个线程、10个线程和100个线程完成累计所需要的时间差。
2.采用多线程方式探测某主机上所有的TCP端口开放情况
importjava.io.*;
Import.*;
classSum{//共享资源,计数器count
privateintcount;//共享资源
publicintadd(){
synchronized(this){//代码段1,共享锁,修饰程序段或者方法
count=count+1;
System.out.println("add:
"+count);
returncount;
}}}
classScanThreadimplementsRunnable{//定义线程
privateSumsd;
privateintsum=0;
privateStringhost;
publicScanThread(Stringname,Sumsd,Stringhost){
this.sd=sd;
this.host=host;
}
publicvoidrun(){//必需的重写
intport;
try{
for(inti=0;i<65535;i++){
port=sd.add();
if(port>65535)break;
try{
Socketcs=newSocket(host,port);
System.out.println("port"+port+"出于开放状态");
cs.close();
}catch(Exceptione){
System.err.println("port"+port+"不能连接");
}
Thread.sleep(100);
}
Thread.sleep(1000);
}catch(Exceptione){
System.err.println("sleep异常");
}}}
classScanDemo{
publicstaticvoidmain(String[]args){
Sumsd=newSum();//代表共享资源的变量
ScanThreads1=newScanThread("线程1",sd,"localhost");//创建完毕
ScanThreads2=newScanThread("线程2",sd,"localhost");
ScanThreads3=newScanThread("线程3",sd,"localhost");
Threadst1=newThread(s1);
Threadst2=newThread(s2);
Threadst3=newThread(s3);
try{
longbegin=System.currentTimeMillis();
st1.start();//使线程运行
st2.start();st3.start();
st1.join();st2.join();st3.join();
longend=System.currentTimeMillis();
System.out.println(“探测localhost的TCP端口,共耗时”+(end-begin)+"毫秒");
}catch(Exceptione){
System.err.println(e.getMessage());
}}}
报告内容:
尝试增加更多的线程,查看测试效率
结合Inetaddress探测主机所处局域网中所有计算机的TCP端口情况
3.TCPSocket多线程通信
importjava.io.*;
import.*;
importjava.util.*;
@SuppressWarnings(value={"deprecation","unchecked"})//查阅该语句作用
publicclassMultiServerextendsThread{
ServerSocketserverSocket=null;
booleanlistening=true;
intport=1080;
intcount;
publicMultiServer(){
try{
serverSocket=newServerSocket(port);
System.out.println("TheChatServerislisteningon"+port);
}catch(IOExceptione){
System.err.println("Can'tlistenonPort");
System.exit
(1);
}
count=0;
while(listening){
try{
newClientServiceThread(serverSocket.accept()).start();
count+=1;
System.out.println("TheChatServerget"+count+"Clients");
}catch(IOExceptione){
System.err.println("Can'tAccepttheClientConnectionApply");
}
}
try{
serverSocket.close();
}catch(IOExceptione){
System.exit
(1);
}
this.start();
}
publicstaticvoidmain(Stringargs[]){
MultiServerms=newMultiServer();
}}
classClientServiceThreadextendsThread{
privateStringname="Client";
privateSocketsocket=null;
privateVectorclients=null;
publicClientServiceThread(Socketsocket){
super("ClientServiceThread");
this.socket=socket;
}
publicClientServiceThread(Vectorclients,Socketsocket){
super("ClientServiceThread");
this.socket=socket;
this.clients=clients;
}
publicvoidrun(){
try{
DataInputStreamin=newDataInputStream(new
BufferedInputStream(socket.getInputStream()));
PrintStreamout=newPrintStream(new
BufferedOutputStream(socket.getOutputStream(),1024),true);
StringinputLine,outputLine;
GreetingProtocolgreeting=newGreetingProtocol();
outputLine=greeting.processInput(null);
out.println("WelcometoMyChatServer,PleaseREGyourName,Format:
name=yourname");
out.flush();
while((inputLine=in.readLine())!
=null){
System.out.println(this.name+"Say:
"+inputLine);
if(inputLine.startsWith("name")){
this.name=
inputLine.substring(inputLine.indexOf("=")+1);
out.println("YourName"+this.name+"isREG");
out.flush();
}else{
outputLine=greeting.processInput(inputLine);
out.println(outputLine);
out.flush();
}
if(inputLine.equals("bye"))break;
}
out.close();
in.close();
socket.close();
}catch(IOExceptione){
e.printStackTrace();
}}}
报告内容:
1)为该程序中,设置服务器最大的链接客户端数量,例如,最大数量为50,当超过这个数字,服务器将主动拒绝新的客户端接入;
2)测试,在你当前所使用计算机硬件环境下,所开设的服务器,可以最实现多少个客户端的链接;
3)将该服务器类有继承Thread,修改为实现Runnable接口。
4.在服务端使用Vector保存客户端信息,并转发信息给所有的客户端;为了保证消息的实时性,在客户端软件分别设立接受线程和发送线程。
//服务器端程序
importjava.io.*;
import.*;
importjava.util.Vector;
classMyServerimplementsRunnable{
staticVectorclients=newVector();
ServerSocketss=null;
MyServer(intport){
try{
ss=newServerSocket(port);//端口号唯一标是本进程
System.out.println("启动本地"+port+"端口");
}catch(IOExceptione){
System.err.println("启动本地"+port+"端口失败");
System.exit
(1);
}}
publicvoidrun(){
Socketcs=null;
try{
while(true){
cs=ss.accept();
clients.add(cs);
clientThreadct=newclientThread(cs);
Threadtct=newThread(ct);
tct.start();
}
}catch(IOExceptione){
System.err.println(e.toString());
}}
classclientThreadimplementsRunnable{
Socketcs=null;
clientThread(Socketcs){
this.cs=cs;
}
publicvoidrun(){
StringinputStr,outputStr;
try{
DataOutputStreamos=newDataOutputStream(cs.getOutputStream());
DataInputS