38.线程池源码结构精讲
ReentrantLock().newCondition()表示生成一个条件;比notify灵活
(1)什么情况下使用线程池?
在系统中如果创建线程+销毁线程的时间大于系统用于完成任务的时间
在Web开发中产生的时间如下:
网络延迟+创建线程时间+调度时间+阻塞时间+线程销毁时间
(2)线程池构成
Executor -> ExecutorService -> AbstractExecutorService -> FutureTask
RejectedExecutionException:线程池已经被销毁,但是后续又再次调用了已经销毁的线程池导致的
39.40.线程池源码精讲
ThreadPoolExecutor -> SynchronousQueue
41.常见面试题分析
(1)什么是OO思想
(2)什么是JRE?什么是JDK?
(3)Java的三大特征分别是什么?
(4)成员变量用static修饰和不用static修饰有什么区别?
(5)如果变量用final关键字修饰,则怎样?如果方法呢?
(6)请举例说明你见过哪些异常
(7)将字符串”I love“存储到磁盘上
JSP底层就是Servlet
Worker ->AbstractQueuedSynchronizer
AQS它是一个Java提供的底层同步工具类,用一个int类型的变量表示同步状态,并提供了一系列的CAS操作来管理这个同步状态
可重入锁有:
synchronized
ReentrantLock,需要手动释放锁
42.Executors与ThreadPoolExecutor
Executors -> ScheduledThreadPoolExecutor
->DefaultThreadFactory -> ThreadFactory -> runnerOffset
守护线程 当进程结束或主线程停止,守护线程也会停止
优先级一般设置为norm_priority ,设的过高或过低都会可能导致饥饿线程(一直得不到运行),本质上是给线程调度器一个提示,默认是5。
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
AbstractExecutorService -> Callable:阻塞的
适配器模式 FutureTask
RunnableFuture extends Runnable, Future
Java类是单继承的 Java接口是多继承的
ThreadPoolExecutor -> execute()
// 线程池核心代码
private final HashSet<Worker> workers = new HashSet<Worker>();
43.JDBC与ClassLoader原理
反射是什么?就是为了在运行时能够获取到本身类信息的一种技术,
还可以动态加载类到JVM
反射机制的核心???初始化后的Class对象
那怎么拿?
(1)对象.getClass();(2)类名.class;(3)TYPE = (Class) Class.getPrimitiveClass(“int”);
Class.forName("com.mysql.jdbc.Driver");
Connection connection =
DriverManager.getConnection("jdbc:mysql://localhost:3306","root","root");
java的类加载机制
怎么样保证加载的类的安全性?
双亲委派机制和Java安全沙箱
每个类加载器都很懒,加载类时都先让父加载器去尝试加载,一直到根类加载器,加载不到时自己才去加载。
44.JDBC与反射、ORM原理
System.out.println();输出对象时,默认调用toString()
反射也不能破坏final关键字
Spring中bean里面的依赖的属性是不是可以通过这种方式来进行注入
Class<? extends Student> clazz = Student.class;
/**
* 创建对象;必须提供一个无参构造器
*/
Student newInstance = clazz.newInstance();
Field declaredField = clazz.getDeclaredField("name");
declaredField.setAccessible(true);
declaredField.set(newInstance, "余生");
System.out.println(newInstance);
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field.getName());
}
ORM框架是什么?对象关系映射
处理的结果集从1开始
StringBuilder线程不安全;StringBuffer线程安全
原因在于StringBuffer在append()方法上使用了synchronized,而StringBuilder没有使用。
45.JDBC与手写ORM框架
在JDK1.8中 字符串用+连接,会在底层生成一个StringBuilder来优化
public class JDBC_Demo {
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
DatabaseMetaData metaData = connection.getMetaData();
ResultSet tables = metaData.getTables("test", null, null, null);
String packName = "com.yuanlong.PO";
String createDir = Utils.createDir(packName);
while (tables.next()) {
// String string1 = tables.getString(1);
// String string2 = tables.getString(2);
String tableName = tables.getString(3);
// 包装一个方法格式化类名
StringBuilder contentBuilder = new StringBuilder();
ResultSet columns = metaData.getColumns("test", null, tableName, null);
Map<String, String> dataMap = new HashMap<>();
contentBuilder.append("package " + packName + ";" + "\n");
while (columns.next()) {
String columnName = columns.getString("COLUMN_NAME");
String dataType = columns.getString("TYPE_NAME");
dataMap.put(columnName, dataType);
// cpmtentBuilder.append("private ")
}
/**
* 1、导包 2、构建类信息 3、构建属性 4、封装属性 5、创建包 6、创建 Java Bean
*/
Set<Entry<String, String>> entrySet = dataMap.entrySet();
for (Entry<String, String> entry : entrySet) {
}
String generateClassName = Utils.generateClassName(tableName);
contentBuilder.append("public class " + generateClassName + "{" + "\n");
for (Entry<String, String> entry : entrySet) {
contentBuilder.append("\t" + "private " + Utils.SQL_TYPE2JAVA_TYPE.get(entry.getValue()) + " "
+ Utils.generateFieldName(entry.getKey()) + ";" + "\n");
}
contentBuilder.append("}");
Utils.writerClazz(createDir + File.separator + generateClassName + ".java", contentBuilder.toString());
System.out.println(contentBuilder.toString());
}
}
}
/**
* 工具类,提供在构建Java Bean时使用的
*
* @author yusheng
* @version 2023年2月2日下午1:02:49
*/
class Utils {
public final static Map<String, String> SQL_TYPE2JAVA_TYPE = new HashMap<>();
static {
SQL_TYPE2JAVA_TYPE.put("VARCHAR", "String");
SQL_TYPE2JAVA_TYPE.put("INT", "Integer");
}
public static String generateClassName(String tableName) {
String clazzName = "";
String[] split = tableName.split("_");
for (String string : split) {
clazzName += (string.substring(0, 1).toUpperCase() + string.substring(1, string.length()));
}
return clazzName;
}
public static String generateFieldName(String columnName) {
String fieldName = "";
String[] split = columnName.split("_");
for (int i = 0; i < split.length; i++) {
if (i == 0) {
fieldName += (split[i].substring(0, 1).toLowerCase() + split[i].substring(1, split[i].length()));
} else {
fieldName += (split[i].substring(0, 1).toUpperCase() + split[i].substring(1, split[i].length()));
}
}
return fieldName;
}
public static String createDir(String packagename) {
String path = null;
try {
String rootPath = new File("").getCanonicalPath() + File.separator + "src";
String[] fileNames = packagename.split("\\.");
for (String fileName : fileNames) {
rootPath += File.separator + fileName;
}
File file = new File(rootPath);
file.mkdirs();
path = file.getCanonicalPath();
System.out.println("生成路径成功");
} catch (IOException e) {
e.printStackTrace();
System.err.println("生成失败");
}
return path;
}
public static void writerClazz(String path, String clazzContent) {
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(new File(path));
fileOutputStream.write(clazzContent.getBytes());
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
File file = new File("");
System.out.println(file.getCanonicalPath());
System.out.println(System.getProperties());
46.IO基本原理
什么叫做流?
InputStream(抽象类):输入流:读
FileInputStream(磁盘 -> 内存)
OutputStream(抽象类):输出流:写
FileOutputStream(内存 -> 磁盘)
会先在JVM缓冲区
// 需要转义
String[] fileNames = packagename.split("\\.");
47.手写JDBC与IO
InputStream resourceAsStream = ThreadPoolDemo.class.getClassLoader()
.getResourceAsStream("data.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
System.out.println(properties.get("path"));
对象到数据库的两种途径:
(1)XML配置文件
(2)注解
注解干嘛用的? 注解就是笔记
在SpringBoot中大量使用注解 把xml替换成yml和properties
注解和反射是离不开的 注解依赖于反射
public @interface 注解名字{}
四个元注解:注解的注解
@Target 指明能用在哪
@Retention 指明在什么时候起作用
@Documented 指明能否形成文档
@Inherit 指明能否被继承
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation {
String name();
}
@TestAnnotation(name = "test")
public class AnnotationDemo {
public static void main(String[] args) {
Class<?> clazz = AnnotationDemo.class;
TestAnnotation annotation2 = clazz.getAnnotation(TestAnnotation.class);
System.out.println(annotation2.name());
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
@TestAnnotation( “test”) //默认加到value上
也可以String name() default “”;
48.JDBC原理
优化手写的JDBC代码
main方法里面尽量不要有逻辑运算
Statement对象.executeQuery() == Statement对象.getResultSet() ???
foreigner写代码时,觉得可以优化代码时,不会在原来的上面优化,而是新建
49.50.一道经典leetcode题
1,A,0;2,B,1;3,C,2;4,D,2
写代码的时候用1、2、3等标识,把可以一起的步骤抽象出来一个方法即可
要在迭代器里remove,不能直接在顺序表里
51.JDBC datasource设计与设计模式
数据库连接池:保活
既然是池子:
(1)肯定要有个容器
(2)连接拿去用了得还回来
(3)保证连接不会重复拿
getConnection()里面用remove方法
适配器模式:适配对象、适配类(先实现后继承)
52.代理模式,计算机网络原理一
静态代理
动态代理:JDK动态代理、CGLIB
Proxy.newProxyInstance()
TCP/IP协议
54.socket编程与操作系统内核原理
UTF-8:可伸缩编码,根据单词或汉字来决定1,2,3个字节编码
55.socket编程与TCP原理详解
MVC:分层是为了简化下层
ARP协议
TCP 首部校验和
TCP包首部
三次握手建立连接时,SYN=1