概述
1.多线程的创建方式2
-
1)自定义一个类实现Runnable接口,
-
2)实现接口里面的run方法--->完成耗时操作
-
3)在main用户线程中创建当前这个类的实例--->"资源类对象"
-
4)创建线程类Thread对象,然后将3)资源类对象 作为参数传递,启动线程!
2.Java设计模式 结构型设计-->代理模式-->静态代理
代理设计模式
代理核心思想
真实角色专注自己的事情(开发中,针对自己的业务) 代理角色帮助真实完成一件事情
静态代理
代理角色和真实角色:要实现同一个接口 动态代理 jdk动态代理 cglib动态代理(需要导入cglib.jar包)
第二种方式实现:
class MyRunnable implements Runnable{} MyRunnable my = new MyRunnable();----> 真实角色 Thread t1 = new Thread(my, "t1") ; ----> Thread代理角色
3.锁
synchronized(锁对象){ //多条语句对共享数据操作 }
锁对象:可以是任意Java类对象,但是多个线程必须使用的同一个锁对象, 否则”锁不住"!
4.解决线程安全
校验多线程安全问题的标准( 使用标准来看多线程环境是否存在问题,以及解决方案)
1)是否是多线程环境---->是 2)是否有共享数据--- > 是 存在的 3)是否有多条语句对共享数据操作 tickets票:多条语句同时操作 将3)多条语句多共享数据的操作使用同步代码块包起来---解决线程安全问题 synchronized(锁对象){ 多条语句对共享数据操作 }
锁对象:
可以是任意Java类对象,但是多个线程必须使用的同一个锁对象, 否则”锁不住"!
什么是同步方法(非静态)?
如果一个方法中第一句话是一个同步代码块,可以将synchronized关键字定义在声明上 权限修饰符1 synchronized 返回值类型方法名(参数列表){ } 锁对象:this---代表类对象的地址值引用 如果是静态的同步方法,锁对象---->当前类名.class(字节码文件对象)
静态的同步方法的锁跟类相关---->当期类的字节码文件对象 类名.class
使用synchronized解决线程安全问题,
安全问题解决了,效率低,可能死锁现象
死锁:
两个线程出现了一种 互相等待的情况, A线程等待B线程释放锁, B线程等待A线程释放锁,造成死锁现象!
解决死锁问题
线程之间的通信必须使用的同一个资源!
5.为什么wait() notify(),线程等待,线程唤醒为什么定义Object类中?
这些方法都是 和锁对象有关系,而锁对象可以是任意Java类对象,而定义object类中 调用wait(),会立即释放锁!
6.throw和throws的区别
throw和throws共同点都是抛出的异常 throws: 1)抛出是在方法声明上抛出 public static Data string2Date(String source,String pattern)throws ParseException { return new SimplateDateFormat (pattern).parse (source); //String datestr ="2022-11-22" //使用s implateDateFormat里面传递的模式"yyy年MM月dd日",跟上面的格式不一致
} 2)throws的后面跟的异常类名,可以跟多个异常类名,中间逗号隔开 3)针对throws抛出的方法处理,谁调用这个方法,谁必须处理! (处理方式---交给调用者,继续throws或者try.. catch... finally) 4)throws它表示抛出异常的可能性
throw: 1)抛出是在方法体语句中 2)后面跟是异常对象名 throw new XXXEception (),只能某个异常对象名
-
throw抛出的处理---交个方法中逻辑语句处理if语句 4)它表示抛出异常的肯定性,执行某段代码-定会有这个异常!
7.jdk5以后Lock锁(接口)--->ReetrantLock可重入的互斥锁
Lock实现提供比使用synchronized方法和语句可以获得的更广泛的锁定操作 实现类: 可重入的互斥锁 java.util.concurrent.locks.ReentrantLock
获取锁:指定的某个时刻 public void lock()
释放锁 : public void unlock()
finally代码:释放资源去使用的,一-定会执行, 除非一种特例(在执行finally之前, jvm退出了)
8.线程池
会创建一些固定的可重复使用的线程数,会在线程池中,循环利用 当某些线程使用完毕,不会被释放掉,而是归还连接池中,等待下一次再去利用! 成本比普通创建线程方式要大!
-
java.util.concurrent.Exceutors工厂类
-
public static ExecutorService newFixedThreadPool(int nThreads)创建固定的可重复的线程数的线程池
-
java.util.concurrent ExecutorService ----->接口的具体实现类public class ThreadPoolExecutor
-
<T> Future<T> submit(Callable<T> task):提交异步任务, 返回值就是异步任务计算的结果;
上面这个的返回值Future : 异步计算的结果---如果现在只是看多个线程是否能够并发的去强转CPU执行权,并没有返回结果,这个返回值可以不用返回! Callable:接口---->异步任务的执行类似于 之前Runnable接口
void shutdown(): 关闭线程池
<T> Future<T> submit(Callable<T> task):提交异步任务,返回值就是异步任务计算的结果; 上面这个的返回值Future :异步计算的结果---如果现在只是看多个线程是否能够并发的去强转CPU执行权,并没有返回结果 这个返回值可以不用返回!
线程池优化------>参数调优(7大参数)
线程池可以重复利用初始化的线程数量 最大线程数量 核心线程数量 最小线程数量 线程执行期间---->计量单位 超过最大线程数量---->启用拒绝策略 ThreadFactory:线程工厂,创建线程池
方法
private volatile int corePoolSize;核心线程数量 private volatile int maximumPoolSize;最大核心线程数 private volatile long keepAliveTime;线程在执行期间的存活时间 TimeUnit unit-->是一个枚举-->时间的计量单位 private final BlockingQueue<Runnable> workQueue,阻塞队列 private volatile ThreadFactory threadFactory;接口; 创建线程的线程工厂--> DefaultThreadFactory实现类是Executors的静态内部类,创建线程的
corePoolSize maximumPoolSize workQueue keepAliveTime threadFactory handLer
private volatile RejectedExecutionHandler handler 拒绝策略当的线程数量已经达到最大核心 线程数.通过上面ThreadFactory创建的线 程不能进入到线程池中;
Java提供了Timer:定时器---执行定时任务TimerTask
java. util. Timer:定时器(可以执行一次或者重复执行某个任务)
构造方法:
Timer():创建一个计时器
成员方法
public void cancel() 取消定时器 void schedule(TimerTask task,Date time) :在给定的日期时间来执行TimerTask定时任务 String dataStr = "2022-11-22 18:00" ;//---->日期文本---->java. util.Date(应用场景:引入使用io流的方式,在指定时间点上,递归删除带内容的目录里面所有的.java文件)
void schedule(TimerTask task,Long delay):在给定多少毫秒后(延迟时间)执行这个定时任务 public void schedule(TimerTask task, Long delay, Long period):在指定延迟时间(delay)执行任务,然后每经过固定延迟时间(period)重夏执行任务
t.cancel();取消定时器
schedule这些方法第一个参数都是定时任务: TimerTask是一个抽象类
1)可以定义具体的于类继承自TimerTask 2)直接可以使用抽象类的匿名内部类
9.IO流
使用java.io.File来描述路径形式
描述"D:EE_ .2211 day23 code Employee. java" File(File parent, String child) File(String pathname)推荐 File(String parent, String child)
基本功能:
创建文件`
public boolean createNewFile()throws IOException: 创建文件,如果不存在,创建,返回true public boolean mkdir(): 创建文件夹,如果存在了,则返回false;否则true public boolean mkdirs(): 创建多级目录,当父目录不存在的时候创建
判断
public boolean isFile(): 是否 是文件 public boolean isDirectory():是否是文件夹 public boolean isAbsolute():是否为绝对路径 public boolean exists():判断文件或者目录是否存在
删除
public boolean delete(): 删除由此抽象路径名表示的文件或目录(删除目录,目录必须为空)
java.io.File ----高级功能:获取指定目录下的所有的文件夹以及文件的Fiie数组
java. io.File:高级功能
-
public File[] listFiles(FileFilter filter) 获取File 数组的时候,就可以直接获取到指定条件的文件名称或者文件夹
-
参数是一个接口: 文件过滤器
-
boolean accept(File pathname):
-
抽象路径名称所表示的路径是否放在File列表中,取决于返回值true, 否则false,不放在列表中
-
public File[] listFiles(FilenameFilter filter):获取File数组的时候,就可以通过文件名称过滤器按照条件进行过滤
-
FilenameFilter接口
-
boolean accept(File dir, String name) :
参数1:指定的目录 参数2:文件名称 返回值: true, 将指定指定I月录下的文件放在File列表中,否则false
例题:获取D盘下所有的以.jpg结尾文件--->输出文件名称
public class FileTest2 { public static void main(String[] args) { //1)描述磁盘上抽象路径的表示d:// File file = new File("D://") ; //public File[] listFiles(FileFilter filter) 获取File数组的时候,就可以直接获取到指定条件的文件名称或者文件夹 /* File[] files = file.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { //抽象路径名称所表示的路径是否放在File列表中,取决于返回值 true,将这个路径放在列表中, // 否则false,不放在列表中 //获取D盘下所有的以.jpg结尾文件--->输出文件名称 // System.out.println(pathname); return (pathname.isFile() && pathname.getName().endsWith(".jpg")); } });*/ //public File[] listFiles(FilenameFilter filter):获取File数组的时候,就可以通过文件名称过滤器按照条件进行过滤 File[] files = file.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { //创建File对象-->判断File是否为文件 File f = new File(dir,name) ;//文件放在指定目录中 //判断f的路径---->指定的文件 并且name文件名称必须以.jpg结尾 boolean flag1 = f.isFile(); boolean flag2 = (name.endsWith(".jpg")) ; return flag1 && flag2 ; } }); //遍历File数组 if(files!=null){ for(File f:files){ System.out.println(f.getName()); } } } }
10.递归算法
方法调用方法本身的一种现象! (并非是方法嵌套方法)
递明的使用:
1)需要定义一简陆 2)有规律 3)必须有出条件----> "死递归"
伪代码 public void show(int n){//5 while(n<0){ break; } System. out. printIn(n) ;//5 show(n--); }
方法递归: 1)需要有方法 2)有一定规律 3)有方法结束的条件(出口条件),否则"死递归"
构造方法没有递归
io流的分类
1)按流的方向划分 输入流---->读 输出流---->写 2)按流的类型划分--同时按方向划分: 字节流: 字节输入流: InputStream--->不能实例化--->具体的子类:针对文件的字节输入流FileInputStream 字节输出流: 0utputStream--->不能实例化--->具体的子类:针对文件的字节输出流FileOutputStrean public File0utputStream(String name, boolean append) throws FileNotFoundException
创建字节文件输出流对象,实现文件的末尾追加,而不将之前覆盖,第二个参数必须为true
字节缓冲流(字节高效流) 字节缓冲输入流:BufferedInputStream 字节缓冲输出流:BufferedOutputStream
字符流: 字符输入流 字符输出流
例题:在当前项目输出一个文本文本,里面同时写入内容
public class IODemo { public static void main(String[] args) throws IOException { //创建字节输出流对象 //OutputStream抽象类,不能new //public FileOutputStream(File file) //public FileOutputStream(String pathname):推荐 直接跟路径名称 FileOutputStream fos = new FileOutputStream("fos.txt") ; //写数据 //public void write(int b) :写一个字节 fos.write(97) ; fos.write("rn".getBytes()); fos.write(98) ; /* fos.write(99) ; fos.write(100) ; //public void write(byte[] bytes):写一个字节数组 byte[] bytes = {65,66,67,68,69,70} ; fos.write(bytes);*/ //释放资源 fos.close(); } }
-
public FileOutputStream(String name,boolean append) throws FileNotFoundException创建字节文件输出流对象,实现文件的末尾追加,而不将之前覆盖,第二个参数必须为true
-
IO流操作的时候,加入异常处理代码格式---->开发中 try...catch...finally 使用捕获一次
11.字节输入流
InputStream--->读 抽象类
提供子类:FileInputStream:针对文件操作的字节输入流
-
1)创建文件字节输入流对象
-
FileInputStream fis = new FileInputStream("fis.txt") ;
-
-
2)读文件
-
public int read() throws IOException:一次读取一个字节,返回字节数
-
public int read(byte[] b) throws IOException:一次读取一个字节数组
-
-
3)释放资源
注意乱码
文件字节输入流一次读取一个字节,将文件内容输出控制台上,中文出现乱码,因为
-
字节流读取字节的时候---将字节--->强转成char,只考虑英文(abcdxxx)--->97---(char)97,当英文的后面有中文拼接
-
无法解析强转了--->乱码---->java才提供了字符流
字节流和字符流的使用时间
什么时候使用字符流,当使用记事本打开能读懂的就使用字符;打开读不懂,用字节!(读图片文件/视频/音频)
例题:当前项目下的IODemo3.java复制到D:EE_2211day24Copy.java
public class IOTest { public static void main(String[] args) throws IOException { //使用字节输入操作---->源文件FileInputStream(String pathname) FileInputStream fis = new FileInputStream("IODemo3.java") ; // 使用字节输出流操作---->目的地文件 FileOutputStream(String pathname) FileOutputStream fos = new FileOutputStream("D:\EE_2211\day24\Copy.java") ; //一次读取一个字节 /* int len = 0 ; while((len=fis.read())!=-1){//不断的再去一次读取字节 //不断写字节 fos.write(len); //写入到流对象汇总 }*/ //一次读取一个字节数组 byte[] bytes = new byte[1024] ; int len = 0 ; //实际字节数 while((len=fis.read(bytes))!=-1){ //字节输出流写一个数组到目标文件中 fos.write(bytes,0,len); } //释放资源 fos.close(); fis.close(); } }
System.currentTimeMillis() ;获取当前时间
12.字节缓冲输出流/输入流 (高效字节流)
BuffedOutputStream/BufferedInputStream:只是提供一个字节缓冲区,本身就是一个字节数组,不会直接操作文件
操作具体的文件使用都是基本字节流FileInputStream/FileOutputStream
-
public BufferedOutputStream(OutputStream out):创建一个字节缓冲输出流对象,默认缓冲区大小(足够大)
-
public BufferedInputStream(InputStream in):创建一个字节缓冲输入流对象,默认缓冲大小
读取方式:
一次读取一个字节
int by = 0 ;//实际字节数 while((by=bis.read())!=-1){ System.out.print((char)by); }
一次读取一个字节数组
byte[] bytes = new byte[1024] ; int len = 0 ; while((len=bis.read(bytes))!=-1){ System.out.println(new String(bytes,0,len)); }
13.字符流
Writer:具体的子类
-
public OutputStreamWriter(OutputStream out):字符转换输出流(可以将基本字节输出流转换成字符输出流),平台默认的字符集编码(idea,utf-8)
-
public OutputStreamWriter(OutputStream out,String charsetName):字符转换输出流 ,指定一个编码字符集
写的功能
-
void write(char[] cbuf)写入一个字符数组。
-
abstract void write(char[] cbuf, int off, int len) 写入字符数组的一部分。
-
void write(int c) 写一个字符
-
void write(String str)写一个字符串
-
void write(String str, int off, int len) :写入字符串的一部分
Reader:抽象类
具体子类
-
public InputStreamReader(InputStream in):创建字符转换输入流,以平台默认字符集解码
-
public InputStreamReader(InputStream in,String charsetName):创建字符转换输入流对象,指定字符集解码
read的功能
-
public int read(char[] cbuf):读取字符数组
-
public int read():读一个字符
-
InputStreamReader/OutputStreamWriter:字符转换流弊端:代码格式复杂,不能直接操作文件!
字符流转换
public InputStreamReader(InputStream in)
public OutputStreamWriter(OutputStream out)
上面字符转换流使用的时候,无法直接直接操作具体文件,里面包装一层字节流操作,书写格式繁琐!
提供了他们具体的子类 ---字符转换流的便捷类,跟idea平台默认字符集一致
-
FileReader(File/String pathname)
-
FileWriter(File/String pathname)
-
FileWriter(File/String pathname,boolean append):第二个参数为true,追加内容
-
字符流针对文件(使用高级记事本打开能读懂的),使用字符流操作
InputStreamReader isr = new InputStreamReader( new FileInputStream("osw.txt"),"gbk") ;//解码gbk InputStreamReader isr = new InputStreamReader( new FileInputStream("osw.txt"),"utf-8") ;解码utf-8 public InputStreamReader(InputStream in):创建字符转换输入流,以平台默认字符集解码
BufferedReader(Reader in):字符缓冲输入流
InputStream in = System.in ; //标准输入流---等待录入 创建字符输入流:Reader抽象类 InputStreamReader是具体的子类 构造方法InputStreamReader(InputStream in ) Reader reader = new InputStreamReader(in) ;
创建一个字符缓冲输入流对象BufferedReader br = new BufferedReader(reader) ;
一步走
BufferedReader br = new BufferedReader( new InputStreamReader(System.in)) ;
利用BufferedReader一次读取一行String line = br.readLine() ;
14.BufferedReader:字符缓冲输入BufferedWriter:字符缓冲输出流
他们不能直接操作文件,提供缓冲区让读写效率更高,特有方式 BufferedReader一次读取一行/可以作为键盘录入(录入一行字符串内容)
字符流针对文本文件(记事本打开能看懂的)-->字符流读写复制
1)字符转换流InputStreamReader/OutputStreamWriter 一次读取一个字符/一次读取一个字符数组 2)使用字符转换流的便捷类FileReader/FileWriter 可以直击操作文件 一次读取一个字符/一次读取一个字符数组 3)使用字符缓冲流BufferedReader/BufferedWriter: 一次读取一个字符/一次读取一个字符数组 4)使用字符缓冲流BufferedReader/BufferedWriter :一次读取一行特有方式(推荐!) 读写复制
15.序列化
将一个Java对象(当前的类以及属性--->签名信息)--->"流数据" 前提条件就是 当前对象的所在类型必须实现
-
java.io.serializable序列化接口---->实现了这个接口的类才能被序列化,产生固定serialVersionUID唯一的标识ID
-
序列化:ObjectOutputStream---->将java对象--->写到序列化流中
-
public ObjectOutputStream(OutputStream out)
-
反序列化:ObjectInputStream---->将序列化中流数据的信息---->还原成Java对象
类的信息一旦更改,里面的类的签名信息(唯一标识 序列化UID就发生变化 )
-
Personc.class------>已经序列化----UId=100
-
现在反序列化的,将Person.class---->改动了----->UId=200
将Person对象变成流数据,进行数据传输,必须实现serializable接口:里面什么都没有 ---"标记接口"
16.java.util.Properties(很重要):属性列表集合类
Properties类表示一组持久的属性。
-
Properties可以保存到流中或从流中加载。(重要的地方)
-
属性列表中的每个键及其对应的值都是一个字符串。
-
继承Hashtable---->实现Map接口---->存储数据,取出数据----都可以使用Map的方式
-
构造方法:public Properties():创建空的属性列表
添加/遍历---可以使用Map集合的方式
1)但是,使用特有功能---->最大特点:键和值必须是string,后期经常用在xxx. properties属性列表文件 key1=value1 key2=value2 2)一些功能和流有很大关系 将属性列表文件的内容加载到属性列表中Properties---->load (Reader in) 将属性列表中的内容保存到指定文件中---->store (Writer out, string文件列表描述) 3)如何读取src'下面的xx . properties配置文件 配置文件在项目下xx. txt
常用的Map遍历方式
获取所有的键的集合 Set<K> keySet() Set<Object> keySet = prop.keySet();
java. util. Properites属性列表有自己的遍历方式---底层基于Map实现的
添加元素:
pubLic Object setProperty( String key,String valve ) 遍历属性列表 public Set<String> stringPropertyNames() 获取属性列表中的所有的键 public String getProperty(String key) 使用此属性列表中指定的键搜索属性
Properties特有方式
public void load(Reader reader)throws IOException : 将指定文件中的内容加载属性集合列表中(内容键值对 key=value) void store(Writer writer, String comments) :将属性列表中的内容保存指定文件中(以"键=值"元素对进行保存) 第一个参数:字符输出/使用字节输出流 第二个参数:属性列表的描述
如何读src下面的xx.properties
1)获取当前类的字节码文件对象 --->Class 正在运行的java类对象 Class clazz = Test3.class ; System.out.println(clazz);
2)Class类---获取类加载器---解析这个里面所有成员(变量/方法..校验) public ClassLoader getClassLoader() ClassLoader classLoader = clazz.getClassLoader();
3)ClassLoader---->public InputStream getResourceAsStream(String name):参数名称:就是src下面配置文件名称 获取资源文件所在输入流对象--->将资源文件的内容读取到了字节输入流中 InputStream inputStream = classLoader.getResourceAsStream("name.properties");
4)将输入流对象的内容加载属性列表中
一步走
前提:配置文件必须在src下面 InputStream inputStream = Test3.class.getClassLoader(). getResourceAsStream("name.properties");
17.网络编程
网络三要素
找到高圆圆 1)网络中需要知道ip地址 2)找到她的ip,对她说话--->对着"耳朵"-----> 端口port 3)对她说话"i Love you"---> 她听不懂, 说"我爱你"---->需要有一个规则----"协议"
ip使用点分十进制法,中间使用.隔开
A类 国家大部门---->前一个号段是网络号段,后面三个主机号段 B类校园/大公司服务器机房/:前面两个网络号段,后面使用两个注解号段 C类私人地址: 前面三个为网络号段,后面是主机号段 192.168.251.1---> port端口 port端口360软件都可以查看你电脑所有客户端软件的端口号: 范围: 0~65535里面0~1024属于保留端口
传输协议
UDP协议-->数据报包(数据包的报文) 1)不需要建立连接通道 2)不可靠协议,不安全的 3)发送数据大小有限制 TCP协议-->最基本的
UDP发送端和接收端的实现(了解)-->不可靠连接
java. net. InetAddress:代表互联网ip地址对象 想获取计算机的主机名称或者获取计算机的ip地址字符串形式? public static InetAddress getByName(String tost) throws UnknownHostException 通过计算机主机名称或者是字符串形式的ip地址--->获取互联网ip地址对象
Socket编程( ”流的套接字")
不管是UDP协议发送数据还是TCP方式发送数据 1)两端都必须有socket对象(Upd发送端 和接收端/ TCP客户端 和服务器端) 2)upd发送端或者TCP客户端都需要有ip地址以及端口 3)socket底层其实一种”物理层”---比特流的方式进行数据发送和接收
UDP接收端的代码实现
-
1)创建接收端的Socket对象,绑定端口
-
2)创建一个接收容器--->数据包--->自定义字节缓冲区,将发送的数据包
-
3)接收
-
4)从接收容器中解析数据包的实际内容数据
-
5)展示数据
Upd方式--->不需要建立连接通道,不可靠连接
Udp发送端的步骤 1)创建发送端的socket,DatagramSocket ds = new DatagramSocket() ;
2)创建数据报包DatagramPacket
-
public DatagramPacket(byte[] buf, 要发送数据---转换成字节数组
int length, 实际字节数长度
InetAddress address, ip地址对象
int port) 端口号
3)使用发送端的Socket将数据存储数据包中,发送(本质存储数据包)send() 4)释放资源close()
最后
以上就是文艺枕头为你收集整理的Java学习第六周1.多线程的创建方式22.Java设计模式 结构型设计-->代理模式-->静态代理3.锁4.解决线程安全5.为什么wait() notify(),线程等待,线程唤醒为什么定义Object类中?6.throw和throws的区别7.jdk5以后Lock锁(接口)--->ReetrantLock可重入的互斥锁8.线程池9.IO流10.递归算法11.字节输入流12.字节缓冲输出流/输入流 (高效字节流)13.字符流14.BufferedReader:字符缓冲输入BufferedWri的全部内容,希望文章能够帮你解决Java学习第六周1.多线程的创建方式22.Java设计模式 结构型设计-->代理模式-->静态代理3.锁4.解决线程安全5.为什么wait() notify(),线程等待,线程唤醒为什么定义Object类中?6.throw和throws的区别7.jdk5以后Lock锁(接口)--->ReetrantLock可重入的互斥锁8.线程池9.IO流10.递归算法11.字节输入流12.字节缓冲输出流/输入流 (高效字节流)13.字符流14.BufferedReader:字符缓冲输入BufferedWri所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复