Java基础知识备忘录(四)

java中的main函数默认为主线程,由JVM创建

Java中的线程

继承Thread,重写run方法

实现Runnable接口,实现run方法,需要依赖Thread类启动(可以实现数据的共享)

建立之后使用start方法调用

线程调度规则:

分时调度:平均分配时间
抢占式调度(Java):按照优先级(优先级高,被执行的概率高,但不是一定)

获取线程的优先级:

getPriority():获取优先级(默认为5)范围:[0,10]
Java中Main主线程的优先级默认也是5、
可获取优先级对应,有一个设置优先级的方法:

想要获取线程的优先级,首先需要获取当前线程的对象:
可以使用Thread类的静态方法在线程内部获取:
Thread.currentThread():

获取线程的名字:

getName():名字是由系统提供的
setName():设置名字

线程的休眠:

Thread.sleep()

线程加入:

join():使线程之间从并行执行转换为串行执行,使当前线程放弃cpu,让调用的线程入cpu执行,结束后才可以继续执行当前线程

Java中的守护线程:

守护线程一般都是为其他线程所服务的,如果守护线程没有守护的其他线程时,守护线程会被终止。

线程的中断操作:
interrupt():设置中断状态,不是强制中断,就是将某个值设置为false,需要在线程内部调用interrupted方法判断是否为设置为中断,可以再中断前做一些处理,如果没有调用interrupted检查状态,线程不会终止。
线程生命周期:
在这里插入图片描述

线程安全问题:

如果有数据共享,就有可能发生线程安全问题,例如多个线程对共享数据的读写,可能同一时刻,各个线程读到的数据不一样,这时可以用加锁解决安全问题:

private Object lock = new Object();
synchronized (lock) {
//type something here
}
线程安全的类:

StringBuffer
Vector
线程不安全的类:
StringBuilder
ArrayList

第二种加锁方式

ReentrantLock:
在需要加锁的代码块前后添加上
lock();加锁
unlock();解锁
记得需要保证解锁步骤
使用try{}catch{}finally{}保证解锁

如果有多个锁,可以使用一样的顺序加锁,避免死锁(顺序锁)

定时器Timer:

计时器任务:TimerTask
可以实现类似JavaScript定时器的作用
可以指定时间后运行,也可以加上时间间隔执行
可以直接终止任务

Timer timer = new Timer();
timer.schedule(new MT(), 2000);	//MT要继承TimerTask类,指定 2 秒后执行
timer.schedule(new MT(), 20002000);//多次执行,间隔为 2 秒

Java网络编程(两个计算机的通信)

什么是IP地址:

网络中计算机的唯一标识
xx.xx.xx.xx (xx为0~255)

IP地址分为局域网IP和外网IP:
局域网:和外界没有联系,但是可以在局域网里互相通信,比如联机玩单机游戏,局域网可以开辟外网通道(一般为192.168.xx.xx)
外网:全球计算机可通信(外网IP一般是共享的,服务器独享)

局域网在内部ip不重复,外网在外网环境中不重复
访问网址的域名其实就是在访问IP地址

DOC命令ping 网址:用来检查网络是否通畅或者网络连接速度的命令
例如测试百度:

> ping www.baidu.com
正在 Ping www.a.shifen.com [180.101.49.11] 具有 32 字节的数据:
来自 180.101.49.11 的回复: 字节=32 时间=27ms TTL=52
来自 180.101.49.11 的回复: 字节=32 时间=27ms TTL=52
来自 180.101.49.11 的回复: 字节=32 时间=31ms TTL=52
来自 180.101.49.11 的回复: 字节=32 时间=28ms TTL=52

180.101.49.11 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 27ms,最长 = 31ms,平均 = 28ms

特殊的ip地址:
127.0.0.1:
表示localhost:本机

IPv6和IPv4:

一般开发使用IPv4
因为上网需要IP地址,但随着计算机数量的增加,IP可能在某一天会用完,为了预防这个问题,创造了IPv6,可以表示的范围更大,使用16进制

Java中表示IP的类:

InetAddress:
可以获取IP地址,参数为地址名称(也可以是计算机名称)
参数也可以是实际IP字符串

InetAddress byName = InetAddress.getByName("localhost");
端口号的作用:

在计算机上有很多软件是需要做通信的,如果有一天信息发送来,如何知道该信息是发送给那个软件的?这时可以使用端口号

总结:

通过ip定位是那个计算机,而通过port定位是那个软件
端口号为一个数字 范围: 0 ~ 65535
IP地址有动态和静态,静态IP需要账号登陆,动态IP只要有网线即可
端口号是也动态的,并不是想要就可以用的,但是可以申请使用

一般申请端口号时会申请4位的端口号,低位的端口号一般被系统服务使用了

通信协议:

多个计算机交流的规则

UDP

速度快(发送消息,不知道是否接收)
不需要建立连接
不可靠

TCP

速度慢
需要三次握手
可靠
网络编程三大协议: IP地址,端口号、通信协议

Socket类(套接字):

在程序中,使用Socket通信,可以设置以上的三个值

DatagramSocket类(UDP):用来接收和发送数据包的Socket
接收数据需要监听,需要提供端口号创建
DatagramPacket用来包装需要传输的数据,同时设置端口号,ip地址,字节数组和字节数组的长度
当Socket使用完后需要关闭

DatagramPacket packet = new DatagramPacket(buf, length, address, port);
datagramSocket.send(packet);
datagramSocket.close();

使用DatagramSocket接收需要使用 receive 方法:

DatagramSocket recive = new DatagramSocket(port);
byte[] buf = new byte[1024];
int length = buf.length;
DatagramPacket datagramPacket = new DatagramPacket(buf, length);
recive.receive(datagramPacket);

当使用recive方法时,程序会停在此处等待接收数据,直到数据到来继续执行,字节数组里就有数据了
接收端接收到数据后,用来接收的数据包就会获得除了数据之外的信息,比如地址

发送端的端口由系统自动分配

使用TCP协议发送数据:

直接使用Socket类发送数据即可,一般使用Socket类建立的端叫做客户端,也成为发送端

新建Socket的发送端(需要设置接收端地ip地端口号,并连接,如果无法连接,则抛出异常)
向外输出数据需要使用IO流,也可从Socket对象中获取输出流:

使用TCP协议数据大小不受限制,UDP数据大小受限制

ServerSocket接收端:
该类一般在服务器端运行,新建实例需要指定监听的端口
由于TCP协议需要连接后才可以输送数据,所以在接收数据之前,调用方法accpet()
accpet():等待连接请求,进行三次握手
accpet可以返回一个Socket实例,在该实例里有发送过来的数据

枚举类型:

枚举类型可以限定值域,增加代码的可读性
枚举类型在Java中以一个类的形式出现
枚举类是用来简化int常量的写法,同时增加安全性(例如不重复)
每个枚举类型的值默认都有一个对应的值,(从0开始递增)

public enum EnumTest {
	A,B,C,D
}

打印数值:

System.out.println(a.ordinal()); // 0
遍历:

values():返回枚举类型的数组,可以直接打印

类的加载机制:

类的使用分成三个部分
类的加载、连接、初始化

程序运行时,系统将要用的java内加载到内存中,加载的时编译后的class文件,class文件包括了数据成员和方法成员,只有在被用到的时候才会加载

类加载器(JVM组件):
将类加载到内存中,并生成java.lang.Class对象
Bootstrap ClassLoader 根类加载器
加载JRE中的核心类

Extension ClassLoader 拓展类加载器
加载JRE中的拓展类
System ClassLoaser 系统类加载器
一般加载自己写的类

Java反射:

在Java中,一般只要用到了Class类,都是应用了反射技术
什么是反射?
在程序运行的时候,查看一个类有那些信息,包括数据成员和方法成员,这个过程称为反射。
怎么使用反射?
要是用反射一般需要获取到要反射的类的Class对象
任何对象都可以使用getClass方法,每个类只有一个Class对象,因为类加载到内存只会被加载一次
,不管有多少个实例
getClass():通过实力获取Class对象
直接赋值获取类对象(不常用):如

Class a = a.class

或者使用Class中的forName方法,但是要抛出异常

Class的反射一般用来将原本不会加载到内存中的类加载大内存中

Class中的方法:

getConstructors:获取类的所有构造方法数组,为Constructor数组
可以使用Constructor的方法构造实例
newInstance():参数我Object类型的可变参数,但是构造出来的实例必须强制转换

获取单个构造器方法
getConstructor():参数为class对象例如:

//实例类A的构造器
public A(String s,int i,double d){

}

//获取该构造器
Class A = class.forName("A");
Constructor c = A.getConstructor(String.class,int.class,double.class);
A a = (A)c.newInstance("",1,1.0);

上述获取构造方法都是public的构造方法
可以获取所有类型的构造方法,包括私有
获取所有声明的构造器:
getDeclaredConstructors():作用同上
getDeclaredConstructor():作用同上

如果需要使用私有构造器,要先解除保护机制
setAccessible(true):解除java的保护机制,可以任意构造对象

同样,Class可以获取(get)字段(Field)和方法(Method),可以获取(get)公开的或是声明过的(Declared),且都可以精确获取和获取所有(s)。

getFields()
getMethod()
getDeclaredField()
getDeclaredFields()
getDeclaredMethods()

字段(Field类的方法):

获取到Field对象,需要获取值:
getInt():获取Int值
getString():获取String值
getDouble():获取double值

方法(Method类的方法):

方法的执行(需要对象):
invoke(对象引用,方法需要的参数):参数如果没有,可以不填,该方法执行返回Object对象作为容器承载方法的返回值,如果没有,则为null

发布了68 篇原创文章 · 获赞 12 · 访问量 5207

猜你喜欢

转载自blog.csdn.net/qq_40963076/article/details/104720857
今日推荐