0303 TCP多线程上传文件,类加载,反射
已经写过单线程的上传文件的方法,那我们怎么样实现多个客户端同时链接服务器上传文件呢
代码展示 服务器端
public class UPload implements Runnable{
private Socket socket;
public UPload(Socket socket) {
super();
this.socket = socket;
}
public UPload() {
super();
}
public void run() {
//明确数据源
//读取客户端发送过来的数据
try {
InputStream in = socket.getInputStream();
//明确目的地文件的位置
File file=new File("F:\\io1127\\server");
//如果文件夹不存在 就创建
if(!file.exists()){
file.mkdirs();
}
//明确文件名
String filename="oracle"+System.currentTimeMillis()+new Random().nextInt(9999)+".jpg";
//明确目的地
FileOutputStream fos=new FileOutputStream(file+File.separator+filename);
//开始复制
byte[] bytes=new byte[1024];
int len=0;
while((len=in.read(bytes))!=-1){
fos.write(bytes,0,len);
}
//回复客户端
//获取字节输出流
OutputStream out=socket.getOutputStream();
//回复内容
out.write("收到".getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
代码展示服务器
public class TCPSever {
public static void main(String[] args) throws IOException {
//创建服务器对象
ServerSocket server=new ServerSocket(8888);
while(true){
//创建连接
Socket socket=server.accept();
//创建线程并开启
new Thread(new UPload(socket)).start();
}
}
}
代码展示客户端(客户端代码没有改变)
public class TCPlient {
public static void main(String[] args) throws UnknownHostException, IOException {
//创建客户端对象明确服务器端的ip和端口号
Socket socket=new Socket("192.168.1.171",8888);
//明确读取数据的数据源
FileInputStream fis=new FileInputStream("F:\\io1127\\3.jpg");
//明确目的地 获得字节输出流
OutputStream out=socket.getOutputStream();
int len=0;
byte[] bytes=new byte[1024];
while((len=fis.read(bytes))!=-1){
out.write(bytes,0,len);
}
//告知服务器端结束
socket.shutdownOutput();
//接收服务器端的回复
InputStream in=socket.getInputStream();
len=in.read(bytes);
System.out.println("服务器端回复:"+new String(bytes,0,len));
//释放资源
socket.close();
}
}
1、类加载
当程序使用某个类的时候,如果该类未被加载到内存中,则系统就会通过加载,链接,初始化三个步骤进行类的初始化
(1)加载,就是将class文件读入内存,并为之创建一个Class对象,在任何一个类被使用的时候会创建一个Class对象,该文件叫字节码文件
图解:

(2)链接,
验证,是否有真做正确的内部结构,与其他类协调一致
准备,负责为类的静态成员分配内存,并设置默认初始化值
解析,将二进制中的符号引用替换为直接引用
(3)初始化,
类的初始化机制(什么时候类被加载到内存)
1、创建类对象
2、类的静态变量或者为静态变量赋值
3、类的静态方法
4、反射
5、初始化某个子类
6、直接使用java.exe运行某个主类
是谁让让类加载到内存中,并为之生成class对象呢,就是类的加载器
类的加载器将.class文件加载到内存中,并为之生成class文件
(1)根类加载器,跟类加载器用于加载jdk中写好的一些类,例如String System类
(2)扩展类加载器,就是加载那些我们引入的那些jar包 jdbc驱动包啊,commensIO之类的jar包
(3)系统类加载器,一般加载我们自定义的类,加载java命令的class文件
那么类已经加载到内存了,那我们如何获得这个Class类的字节码文件,并获得里边的多有内容呢
获取字节码文件对象,获取这个类所有的成员变量也好成员方法也好等等这些东西,这个过程就叫做反射。
获取Class类字节码文件的方式 三种
先创建一个Person类
public class Person {
private int age;
String name;
public Person() {
System.out.println("public person()");
}
private Person(String name) {
System.out.println("private person(String name)");
}
public void eat(){
System.out.println("public void eat()");
}
public void sleep(String name){
System.out.println("public void sleep(String name)");
}
}
创建测试类 获取字节码文件
public static void main(String[] args) throws ClassNotFoundException {
//通过object中getclass方法 获取字节码对象
Person p=new Person();
Class c=p.getClass();
System.out.println(c);
//通过类名调用class属性获取
Class c2=Person.class;
System.out.println(c2);
//forname 方法
Class c3=Class.forName("com.oracle.demo02.Person");
System.out.println(c3);
}
‘
能够获取到字节码文件 怎样获取里边的构造方法并且使用呢
在反射机制中,把类中的成员(构造方法、成员方法、成员变量)都封装成了对应的类进行表示
构造方法使用类Constructor表示
这个构造方法类中提供了返回构造方法的方法,我们先看返回一个构造方法的方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)获取public修饰指定参数类型的构造方法
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)获取指定参数类型的构造方法(公有和私有都包括在内)
构造方法类Constructor中有一个public T newInstance(Object... initargs) 方法 创建一个构造方法类对象
代码展示
public static void main(String[] args) throws
ClassNotFoundException, NoSuchMethodException,
SecurityException, InstantiationException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
//获取字节码文件对象
Class c=Class.forName("com.oracle.demo02.Person");
//获取字节码文件对象构造方法 公共
Constructor con=c.getConstructor();
System.out.println(con);
//创建对象
Person p=(Person)con.newInstance();
p.eat();
}

浙公网安备 33010602011771号