目录
(一)泛型与枚举
- 泛型 实质是一个类型占位符,单一字母表示
//泛型类 -在加载时声明
public class person<T,E>{
T son;
E wife;
}
-非T类型
public class person<T>{
void play(M operation){}
}
//泛型方法
-在类加载时声明
public class Person<T>{
void play(T operation){}
}
//静态泛型方法
-静态方法和类无关也需声明
public class Person{
static <Q> void eat(Q food){}
}
//泛型接口
-实现类声明
public interface Person<T>{
void eat(T food);
}
public class Niger implements Person<String>{
void eat(String food);
}
public class Niger<E> implements Person<E>{
void eat(E food);
}
//泛型擦除模式
-在代码运行阶段,类型被擦除
public class Person<T>{
void play(T operation){}
}
Person<String> perS = new Person<String>();
Person<Integer> perI = new Person<Integer>();
perI.getClass() === perS.getClass();
//泛型通配符 -泛型的继承关系与java原生不一致
public class Person<T>{
void play(Person<T> operation){}
}
Person<Number> perN = new Person<Number>();
Person<Integer> perI = new Person<Integer>();
erro:perN.operation(perI);
-重新绑定 ?为所有泛型类的父类,所有不受声明的限制
public class Person<T>{
void play(Person<?> operation){}
}
Person<String> perS = new Person<String>();
Person<Integer> perI = new Person<Integer>();
success:perS.operation(perI);
//泛型的上下边界
public class Person<T>{
-传入必须是T或T的子类,用于查看
void play(Person<? extends T> operation){}
-传入必须是T或T的父类,用于写入
void play(Person<? super T> operation){}
}
- 枚举 系统变量有固定的取值选择,预先定义的常量类,封装存自己的静态常量类
//语法
public enmu 类名{
枚举项2; 枚举项1;
枚举项属性声明;
构造器;
geter取值器;
}
//规则
-枚举项名 大写用下划线分割,相当于对象名
-枚举项属性 可以初始化值,调构造方法
-继承 默认Enum类 -封装 只含有私有属性
-多态 允许实现接口
public enum Code implements Val{
REQUEST_FAIL_PARAMS(200,"请求参数错误!"),
REQUEST_FAIL_METHON(201,"请求方式错误!"),
REQUEST_FAIL_URL(202,"请求地址错误!");
private Integer status;
private String message;
piblic Code(){}
public Integer getStatus(){
return this.status;
}
public String getMessage(){
return this.message;
}
}
//枚举类的比较
Code.REQUEST_FAIL_PARAMS == Code.REQUEST_FAIL_PARAMS
-因此可使用Switch匹配
switch(ca){
case Code.REQUEST_FAIL_PARAMS:
throw new Exception();
break;
default:
break;
}
(二)多线程基础
- 基础知识
-任务:在一个时间做的一件事情。
-线程: 进程中的一个执行单元,负责程序的执行。一个进程至少包含一个线程。
-进程:内存中运行的应用程序,每个进程有独立的内存空间,一个应用程序可同时运行
多个进程,是系统运行的基本单位,
-并发:多件事情在同一时间段内发生。相对于一个cpu,交替运行。
-并行:多件事情在同一时刻在发生。相对于多cop,同时运行。
-同步:消息通讯机制,等待调用结果
-异步:消息通讯机制,不影响调用方
-线程调度:资源的分配问题。
-分时调度:轮流使用cpu,平均分配cpu时间。
-抢占式调度:取优先级高的,相同则随机。(java选择)
- 线程的创建方式
//继承Thread类,实现抽象方法run()
-匿名内部类
-不适合资源的共享
-不适合在继承
new MyThread extends Thread{
@Override
public void run(){}
}
-匿名对象
new Thread(new MyThread()).start();
MyThread thread = new MyThread();
-重新分配栈空间
thread.start();
//实现Runnable接口,实现run方法
//函数式接口
class MyThread implements Runnable{
@Override public void run(){}
}
MyThread interface = new MyThread();
Thread thread = (Thread) interface;
thread.start();
//常用方法
thread.setPriority();
-抢占资源的可能性改变
-Thread.MAX_PRIORITY
-Thread.MIN_PRIOTITY
-Thread.NORM_PRIORITY
thread.currentThread().getName(); thread.setName();
-当前线程睡眠多少毫秒
Thread.sleep();
-可能性让步资源,放手后会在竞争
Thread.yield();
-线程合并,打断调用线程的执行,完成后继续,等待个结果
thread.join();
-设置为守护线程,调用线程结束则结束
thread.setDasemon(true);
- 线程的生命周期
-new 新建状态:创建对象后进入
-runnable 就绪状态:start() 运行后进入
-running 运行状态:获得资源后,CPU调度时进入
-block 阻塞状态:运行时,暂时放弃资源时进入 -等待阻塞:运行时,执行了wait()
-同步阻塞:获取同步锁失败,竞争失败时
-其他阻塞:调通了线程的sleep(),join()等方法,或者I/O处理中, 结束后进入就绪状态。 -dead 死亡状态:线程执行完,或异常退出进入
- 线程的安全问题
-多个线程竞争资源时,同一资源在切换时,被其他线程抢占,非原子操作,导致数据不一致,导致读写操作冲突。
//同步代码块
synchronized(同步锁){
-相当于原子操作了
-锁可以为任意对象的实例
-多个线程使用一把锁
-保证唯一,且能拿到
-this
-new Object()
-MyThread.class
}
//同步方法
-修饰普通方法锁就是本类对象
public synchronized void operation(){}
//Lock
-互斥锁
Runnable run = new MyThread();
new Runnable(
@Override
public void run(){}
)
Thread thread1 = new Thread(run,"thread1");
-对数据加锁
private Lock l = new ReenternLock();
try{
l.lock(resoure);
}finally{
l.unlock(resoure);
}
//线程的协作
-有序的完成事务,需要通知
-等待唤醒机制,线程通信
-协调锁
-必须在同步块中,由锁作为中间者调用这个方法
Object lock = new Object();
-线程一
-线程二
-线程一
-线程一等待
synchronized(lock){
-等待时,会释放锁,进入等待池
lock.wait();
-唤醒后重新竞争
lock.wait(timeout)
-自己唤醒,不在执行后面的代码
}
-线程二唤醒
synchronized(lock){
lock.notify();
-唤醒所有线程
lock.notifyAll();
}
//线程的死锁
-当线程互相等待对方唤醒时,会进入死锁
-拿到对方需要的资源不释放
-线程一
synchronized(lock2){
lock2.sleep();
-不释放
synchronized(lock1){
}
}
-线程二
synchronized(lock1){
lock1.sleep();
-不释放
synchronized(lock2){
}
}
- 线程的线程池
-对线程的管理,需要时使用,重复利用。
-执行和销毁很消耗CPU。
-提高响应速度,提交创建了。
-Excutors执行线程池,为创建工具
-ExcutorsService为线程池接口
-固定数量
Excutors.newFixedThreadPool(size);
-可伸缩
Excutors.newCacheThreadPool();
-单线程(有序)
Excutors.newSingleThreadPool();
-定时线程池
Excutors.newScheduledThreadPool(size);
pool.schedule(Runnable,delay,TimeUnit.SECONDS);
pool.isTerminated() //是否完成
MyRunnab thread = (MyRunnable) new Runnable();
//提交Runnable接口对象
pool.sumbit(thread);
pool.sumbit(thread);
pool.sumbit(thread);
//关闭线程池
pool.shutdowm();
- 线程的有返回值创建
//Callable
class HandleCallable implements Callable<返回值类型>{
@OverRide
public 返回值类型 call(){}
}
//借助线程池
ExcutorService pool = Excutors.newFixredThreadPool();
HandleCallable t1 = new HandleCallable();
HandleCallable t1 = new HandleCallable();
Future<Integer> result = pool.sumbit();
pool.shutshowm();
- 线程安全的集合
-CopyOnWriteArryList<> ----ArrayList 写入锁,加锁,通过拷贝,还给原来数组
-CopyOnWriteArrySet<> --- Set
-CopycurrentHashMap<>---对默认容量Segement,分段加锁
(三)注解与反射
- 注解(Annotation) JDK5.0引入,可被编译器读取,配合反射实现功能
//格式
@注释名(参数列表)
//常见注解
@Override 重写
@Deprecated 废弃的方法
@SupressWarmings 镇压警告
//元注解
@Target 用于描述注解的使用范围和位置
@Rentention 注解信息的保存范围(SOURCE>CLASS>RUNTIME)
@Document 说明注解保存在javadoc文档中,转字节码还能生效
@Inherited 说明子类可以继承该注解
//自定义注解
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Renention(value = RenrntionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotation{
-类型 类型名();
String name();
String sex() default "男";
-一个参数命名为value()时可以省略
}
@MyAnnation(name = "小付")
void method();
- 反射 动态性改变和运行
//动态语言
-在运行时,可以改变自身结构
-java准动态性,会损失效率
Reflection
-正常方式
引入需要的包类名称->通过new实例化->取得实例对象
-反射方式
实例化对象->getClass()方法->得到完整的"包类"名称
//加载完后,方法区会产生一个Class对象,可以得到完整的结构信息
-可以实现动态的创建对象和编译
-本质是一种解释操作,会影响效率
-获取Class对象
-一个类类型和维度只含有一个Class对象
Person person = new Person();
Class c1 = person.getClass();
Class<Person> c2 = Person.class;
Class c3 = Class.forName("com.fzy.reflection.user");
Class c4 = Integer.TYPE;
Class c5 = c1.getSuperclass();
//一些类的class()对象
Class c1 = Object.class;
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = int[][].class;
Class c5 = ElementType.class;
Class c6 = Integer.class;
Class c7 = void.class;
Class c8 = Override.class;
Class c9 = Class.class;
-获取类信息
Class c = Class.forName("com.fzy.reflection.User");
-获得包名加类名
c.getName();
-获得类名
c.getSimpleName();
-获得属性
Filed[] fields = c.getField();
-获得指定属性的值,public
Field name = c.getField("属性名");
-获得指定属性的值,全部
Field name = c.getDeclaradField();
-获得方法,本类及父类public
Method[] methods = c.getMethods("属性名");
-获得方法,本类
Method[] methods = c.getDeclaradMethod();
-获得指定方法
Method method = c.getMethon("setName");
-获得指定构造器 public
Constuctor[] constuctors = c.getCostructors();
-获得构造器 全部
Constuctor[] constuctors = c.getDeclaredCostructors();
-获取指定,参数列表
Constuctor constuctor = c.getCostructor();
- 底层原理
-加载 将class文件字节码内容加载到内存中,将静态数据转化到方法区
-连接 将java二进制代码合并到JVM的过程
-验证 确保加载类符合规范,没有安全问题
-准备 为static信息在方法区分配空间并且初始化默认值
-解析 虚拟机常量池符号替换为地址的过程
-初始化 执行类构造i器,初始化父类,线程加锁
.JAVA文件(源程序) -编译器 .class字节码文件 -类装载器 类缓存 -字节码校验器 -解释器 操作系统平台
-类加载器
ClassLoader systemClass = ClassLoader.getSystemClassLoader();
ClassLoader parnet = systemClass.getParent();
Class.forName().getClassLoader()
//BootStrap Classloaer -- 加载rt.jar核心包 -c++编写
//Extension Classloader --ext下包加载器
//System.Classloader --App,项目包加载器
//自定义加载器
-获取系统加载器加载路径
System.getProperties("java.class.path")
//双亲委派机制
当已有加载文件加载器,则自定义同名类无法加载
- 实践使用
Class clazz = Class.forName();
-默认调用无参构造器
String str = clazz.newInstance();
-有参实例化
Consturctor cs = clazz.getyDelareConstuctor(param..);
String str = cs.newInstance(param...);
-通过反射调用方法
Method setName = c.getDeclaradMethod(setName,String.class);
setName.invoke(str,"name");
-通过反射调用属性
Field name = class.getDeclaraField("name")
name.set(str,"name");
//关闭权限检查 private 提高效率
name.setAccessible(true);
str.getName()
//当前系统时间戳
System.currentTimeMillis()
-泛型的反射
-ParameterizedType 参数化类型 List<String>
Student.class.getMehod()
//获得泛型参数类型
method.getGenericParamterTypes()
(ParameterizedType) paramTypes
//获得泛型返回性类型
method.getGenericReturnTypes()
(ParameterizedType) paramTypes
-注解的反射
ORM --对象关系映射
//注解
@Target(ElementType.TYPE)
@Retention(RentenionPolicy.RUNTIME)
@interface TraslateClass{
String value();
}
@Target(ElementType.FIELD)
@Retention(RentenionPolicy.RUNTIME)
@interface TraslateField{
String column();
String type();
int length();
}
@TraslateClass("db_student")
class Student{
@TraslateField(
column = "stu_name"
,type = "varchar"
,length = 10)
private String name;
@TraslateField(
column = "stu_id"
,type = "int"
,length = 10)
private Integer id;
}
//类注解值
Class c = Student.class;
TraslateClass traslateClass = (TraslateClass)c.getAnnotation(TraslateClass.class);
String value = traslateClass.value();
//字段注解值
Field f = c.getDeclaredField("name");
TraslateField traslateField = (TraslateField) f.getAnnotation(TraslateField.class);
String column = annotation.column();
(四)函数式编程
- 定义:有且只有一个抽象方法的接口,使用于lambad.
- 语法糖:指简化代码而不改变功能的代码。例如foreach()利用的迭代器
@FunctionalInterface
public interface Lambad{
/public abstract/ void method();
//@FunctionalInterface用于接口检测是否为函数式接口,导致编译成功或失败
}
- 函数式接口的使用
//作为参数使用
static void show(Lambda interface){}
show(new LambdaImpl())
show(new Lambda(){
//匿名内部类方式简化
//拥有class文件
@Override
void method();
})
show(()->{
//lambda表达式简化
//代表重写其唯一的抽象方法
});
show(()-> sout;);
//优化参数浪费 会在使用时调用执行
@FunctionalInterface
public interface Message{
String builder();
}
void show(int level,String message){
if(level == 1){
sout;
}
}
show(2,()->{
return msg1+msg2;
})
- 函数式编程
//接口作为参数
class MyRunnable{
static void start(Runnable run){
new Thread(run),start();
}
}
start(new Runnable(){
@Override
void run{}
})
start.(()->{
//重写方法run()
})
//作为返回值替代函数式接口 按字符串长度排序
static Copmarator<String> getComparator(){
//匿名内部类方式
return new Comparator<String>(){
@Override
int compare(String str1,String str2){
return str1.length()-str2.length();
}
}
//lambad简化方式
return (String str1,String str2)->{
return str1.length()-str2.length();
}
//再次简化 代表就是接口的抽象方法的实现
return (str1,str2)-> str1.length()-str2.length();
}
String[] arr = {"aa","a"};
Arrays.sort(arr,getComparator());
- 常用的函数式接口
-Supplier接口 get()获取一个指定泛型对象 生产型接口
static String getString(Suppiler<String> sup){
return sup.get();//返回的是String对象
}
getString(()->{
//get方法体
return "初始化";
})
getString(()->"初始化");
//自己尝试
static User builderUser(Suppiler<User> sup){
return sup.get();//返回的是String对象
}
builderUser(()->User
.builder()
.name("软件工程师")
.age(22)
.build());
//Consumer 消费型接口,accpect()使用指定泛型的数据
static void using(String thing,Consumer<String> con){
con.accept(name);//将数据传入重写方法使用
}
using("软件工程师",()->{
new StringBuilder(name).reverse().toString();
})
-原生方法 andThen() 需要两个Conmuser接口方法组合后使用
Consumwer<> con1;
Consumwer<> con2;
String name = "";
con1.andThen(con2);//一用完二用
//可以形成一条链路
static void using(String thing,Consumer<String> con1,Consumer<String> con2){
con1.accept(name);
con2.accept(name);
String name = thing;
=== con1.andThen(con2).accpet(name);//一用完二用
}
using("软件工程师",
(name)->{
new StringBuilder(name).reverse().toString();
},
(name)->{
new StringBuilder(name).reverse().toString();
})
// Predicate 对数据进行判断返回布尔 test()
static boolean check(String s, Predicate<String> pre){
//test()的lambda是判断逻辑
return pre.test();
}
多条件拼接 and(),or()
pre.or(pre2)
//Function 数据类型转换apply()
private static Record paras(Order order,Function<Order,Record> pas){
return pas.apply(order);
//Function<R,T>第二个参数为返回值类型
}
-andThem 连续转换
(五)IO流
- 文件
//计算机文件
转义字符--\ 斜杠
linux系统下
相对路径:./(当前路径) ../(上级路径)
绝对路径:硬盘路径 /usr/soft/
windows系统下
绝对路径:C:\\soft\\
//对File的操作映射实例 实现Comparablie和Serializable接口
Output:将内存持久化(硬盘,数据库)设备为输出
cenput:将持久设备中读取到内存
-创建
new File(String name); //文件夹
new File(String path,String name);
new File(String parent,String child);
dir,createNewFile()
-操作
file.getPath()
file.getName();
file.getAbsolutePath();
file.getParent();
file.isAbsolute();
file.isDirectory();
file.isFile();
file.exists();
-文件删除
file.delete();
dir.delete() //无子文件
- 输入输出流
-字符流:处理字符相关,文本数据,以一字节(8位)为单位,
-字节流:处理字节相关,如声音,图像。能处理所有文件。
字符:
-Reader(字符读取流)
-BufferedReader(缓冲读取流)
-InputStreamReader(字符读取流)
-FileReader(文件读取流)
-StringReader (字符数组读取流)
-Writer(字符写入流)
-BufferedWriter(缓冲写入流)
-OutputStreamWriter(字符写入流)
-FileWriter(文件写入流)
-StringWriter(字符数组写入流)
字节:
-InputStream (字节输入流)
-FileputStream(文件输入流)
-BuffereInputStream(缓冲输入流)
-ObjectInputStream(对象输入流)
-ByteArrayInputStrean(字节数组输入流)
-OutputStream(字节输出流)
-FileOutputStream(文件输出流)
-BuferedOutputStream(缓冲输出流)
-ByteArrrayOutputStream(字节数组输出流)
-ObjectOutStream(对象输出流)
- 常用字节流详解
-InputStream 字节输入流
//读取单个字节,返回0-255范围内的int字节值,无则返回-1
int read();
//从管道中读取一定数量的字节,并缓冲到数组buf中,返回读取数量
int read(byte[] buf);
//从管道中,跳过并丢弃n个字节的数据
long skip(long n);
//返回管道中字节数
int available();
//关闭流并释放系统资源(线程的阻塞)
void close();
-FileInputStream 文件字节输入流
//创建相关流对象
File file = new File(path,name);
InputStream in = new FileInputStream(file);
//操作
-对于汉字等UNICODE读取不正常
int point = in.read();
char data = (char)int;
long skippoint = in.skip(2);
byte[] data = new byte[2];
//一次性读完
byte[] dataAll = new byte[in.available()];
//读取缓冲区长度的数据
while(int dataLength = in,read(data)){
//GBK中英文占两个字节
//UTF-8中文占三个,英文占一个
sout(
new String(data,0,dataLength,"UTF-8")
);
}
-OutputStream 字节输出流
//写入一个字节到缓冲管道
void write(int data);
//写入一个字节数组的数据到缓冲管道
void write(byte[] buf);
//将缓冲管道中数据清空,同时写入硬盘
void flush();
//释放资源
void close();
-FileOutputStream 文件字节输出流
//输出文件地址
new FielOutputStream(String name);
//输出文件对象
new FileOutputStream(File file);
//是否可以追加内容
new FileOutputStream(File file,boolean append);
//操作
OutputStream out = new FileOutputStream(dir+name);
- 缓冲字符输入输出流
-缓冲区:预留数据,临时存储,像漏斗
-避免大量的直接IO操作磁盘,磁盘读取慢
-采用中包装设计模式,预先读取,少了再读
-默认缓冲区大小8192(8kb)
-缓冲区满时,则会自动操作磁盘
//BuferedInputStream
//BuferedOutputStream
int read();
int read(byte[] buf,int off,int len)
int write();
int write(byte[] buf,int off,int len)
void flush()
void close()
- 常用字符流
-Reader 字符写入流
//读取单个字符
int read();
//读取一定量的字符。进入缓冲数组中
int read(char[] chuf)
//创建 调用父类的FileInputStream的构造方法
-FileReader
new FileReader(String path);
while(isOverAndData = reader.read() == -1){
(char)isOver;
}
char[] c = new char(1024);
int length = reader.read(c,0,len)
- Writer 字符写入流
new FileWriter(String name,isappend)
//按照ascll码表转换
void write(int c);
//实现了
void flush()
int write();
int write(byte[] buf,int off,int len)
void flush()
(六)网络编程入门
-BIO,NIO,AIO
- NIO JDK1.4替代IO的网络编程工具(同步非阻塞)
-阻塞IO 通常在同步I/O操作时,流打开会阻塞线程运行,就要多个线程,也叫传统IO(串行)
-非阻塞IO 采用Reactor的工作方式,延迟IO操作,等待系统通知,也称NIO (并行)
-核心组成
-Channels 双工通信,FileChannel,DoubleChannel
-Buffers 缓冲区
-Selectors 单线程处理多个Channel的操作,多路复用
- Channel
-封装了对数据源的操作
-依赖于缓冲区
-不同操作系统实现不同
-可以异步操作
-通道之间的数据传输transferform
-分散和聚集scatter(多个buffer写入)和gahter(多个buffer读取)
channel.read(ByteBuffer[])
channel.write(ByteBuffer[])
-FileChannel
interface Channel extends Closeable{
boolean isOpen();
void close();
}
- -FileChannel
//读取 随机访问流
RandomAccessFile file = new RandomAccessFile(String path,rw--read/write)
FileChannel channel = file.getChannel();
//分配缓冲区
buf = ByteBuffer.allocate(1024);
int read = channel.read(buf);
while(read != -1){
//因为刚从磁盘写入buf,得移动指针到第一位置(读写模式切换)
buf.filp();
//在从buf中调取,是否有剩余
while(buf.hasRemaining){
(char)buf.get();
}
//清空后才能在读
buf.clear();
read = channel.read(buf);
}
channel.close();
===================
磁盘-通道-缓冲区-系统
===================
//写入
RandomAccessFile file = new RandomAccessFile(path,"rw");
FileChannel channel = file.getChannel();
ByteBuffere buf = ByteBuffer.allcate(1024);
String data;
buf.clear();
buf.put(data.getBytes());
buf.filp();
while(buffer.hasRemaining()){
channel.write(buf);
}
channel.close();
===================
系统-缓冲区-管道-磁盘
===================
channel.position();//文件空洞
- SocketChannel interface
-extends Seclecor 管理多个Socket连接
-本身不存数据,负责监听
-Socket和Socket通道(可复用)
-阻塞和非阻塞可选择 isBlockingLock()
三种监听器
-DatagramChannel UDP
...见专门笔记
-SocketChannel TCP
...见专门笔记
-ServerSocketChannel 网络通信
使用
int port = 8080;
//自定义缓冲区
ByteBuffer buf = ByteBuffer.wrap("".getBytes())
ServerSocketChannel ssc = ServerSocketChannel.open();
//绑定监听端口
ssc.socket().bind(new InetSocketAddress(port));
//设置非阻塞模式
ssc.configureBlocking(false);
//监听端口连接
while(true){
//获取连接的socket
SocketChannel sc = ssc.accpet()
if(sc != null){
//指向0
buf.rewind();
//通过管道写入磁盘文件
sc.write(buf);
sc.close();
}
}
- Buffer
-数据传输的中介,一个内存非磁盘
写入buffer
调用filp()模式切换
读取buffer
clear()全部compact()读过的
-capacity 固定容量
-position 绝对位置
-limit 每次读写的长度
缓存区分片 slice 子缓冲区 数据共享
只读缓存区
直接缓冲区
内存映射文件 IO
- Selector
多路复用器
-检查多个通道的状态(网络连接)
-单线程处理
-复用继承的SelectableChannel
-通道注册Channel.register(Selector sel,int opts)
SelectionKey.OP_READ
SelectionKey.OP_WRITE
SelectionKey.OP_CONNECT
SelectionKey.OP_ACCPECT
监听事件类型,将要发生的就绪状态
//创建
Seclector.open();
//注册(不能是FileChannel)
ServerSocketChannel.open();
ssc.configureBlocking(false);
ssc,bind(new InetSocketAddress(port))
ssc.register(selector,SelectionKey.OP_ACCPECT);
//轮询查询就绪的通道操作 就绪状态集合
Set<SelectionKey> sk-= selector.selectionKeys();
Iterator<SelectionKey> it = sk.iterator();
while(it.hasNect(){
SelectionKey k = it.next();
//就绪状态操作
if(key.isAccpet()){
}
it.remove()
})
- 线程通讯 Pipe
//获取管道
Pipe p = Pipe.open();
//获取sink通道
Pipe.SinkChannel sink = pipe.sink();
//写入数据
ByteBuffer data = ByteBuffer.allocate(1024);
data.put("".getBytes())
data.filp();
sink.write(data);
//获取source通道
PipeSourceChannel sc = pipe.source();
//创建缓冲区,读取数据
ByteBuffer buf = ByteBuffer.allocate(1024);
buf.flip();
int length = sc.read(buf);
new String(buf.array(),0,length);
//关闭通道
sc.close();
==================================================
线程A缓冲区->sink通道->pipe->source通道->线程B缓冲区
==================================================
- 文件锁 FileLock
排他锁:又叫独占锁,阻止其他进程读锁
共享锁:其他进程只能读,不能写
new FileChannel()
FileLock lock = channel.lock();
lock.release()
//阻塞式
lock(long position,long size,booleam share);
//非阻塞
tryLock();
isShared();
AsychronousFileChannel
//创建异步文件通道
Parh path = Path.get(String path);
AsychronousFileChannel asy = AsychronousFileChannel.open()
//创建缓冲区
ButeBuffer.allocation(1024)
//调用read
Future<Integer> f = asy.read(buf)
//是否完成
while(f.isdone()){
读取
buf.filp();
byte[] data = new byte[buf.limit]
buf.get(data)
while(buf.remaining()>0){
buffer.get()
}
buf.clear;
}
(七)Optional类
//创建optional
-为空指传递会抛出异常
Oprional<Student> opt = Optional.of(stu1);
-对象可能为空可能不为空
Optional<Student> opt = Optional.ofNullable(stu2);
//获取包装对象
opt.isPresent();
opt.get();
//兜底方法 没有则返回默认对象
stu4 = Optional.ofNullable(stu3)
.orElse(defaultStu);
OR 返回某个属性
stu = Optional.ofNullable(stu4)
.map(templeStu->templeStu.getName())
orElse("xiaoming")
(八)集合框架进阶
- stream 串行的集合操作处理
数据元素集合-->生成流-->中间操作-->最后操作
//生成
List list = Arrays.asList("","";)
list.stream()
//遍历操作
.map(obj -> {
obj处理
})
//收集
.collect(类型);
- filter
list.stream()
.filter(obj -> {
返回布尔(过滤条件)
})
.collect(Collectors.toList);
- map
list.stream()
.map(obj -> {
UserDTO给前端
})
.collect(Collectors.toList);
- limit
list.stream()
.map(obj -> {
UserDTO给前端
})
限制数量
.limit()
.collect(Collectors.toList);
- sorted
.collect(Collectors.toList);
sorted
list.stream()
//默认升序
.sorted(
Comparator.comparing(Student::getAge())
)
/.reversed()
.collect(Collectors.toList);
- allMatch/anyMatch
-一个元素符合
boolean = list.stream()
.allMatch(obj -> {
条件
})
-符合全部
boolean = list.stream()
.anyMatch(obj -> {
条件
})
- max/min
list.stream()
.max(
Comparator.comparing(Student::getAge())
返回布尔(过滤条件)
)