1.多线程的实现方案(三种)
1.1.继承Thread类
通过自己的类直接extend Thread,并重写run()方法,就可以启动新线程并执行自己定义的run()方法
class MyThread extends Thread{
public void run(){
System.out.println("My Thread.run()");
}
}
启动线程
MyThread myThread1 = new MyThread();
myThread1.start();
1.2.实现Runnable接口
Java程序里面对于继承永远都是存在有单继承局限的,如果自己的类已经extends另一个类,就无法直接extends Thread,Java里面又提供第二种多线程的主体定义结构形式:实现java.lang.Runnable接口
实现一个Runnable接口:
public class MyThread extends OtherClass implements Runnable {
public void run() {
System.out.println("MyThread.run()");
}
}
启动MyThread,首先实例化一个Thread,并传入自己的MyThread实例:
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
1.3.实现Callable接口
实现Callable接口的线程,可获取返回值
使用FutureTask get()方法获取返回值,get()方法是阻塞的,会一直阻塞主线程等待返回结果。
class MyThread2 implements Callable {
public String name;
public MyThread2(String name) {
this.name = name;
}
@Override
public Object call() throws Exception {
for (int i = 0; i < 4; i++) {
System.out.println("这是线程" + this.name + ":" + i);
}
return name + "执行完成";
}
}
实现类中:
MyThread2 myThread1 = new MyThread2("线程A");
FutureTask futureTask1 = new FutureTask(myThread1);
new Thread(futureTask1).start();
2.ArraysList和LinkedList的区别
2.1.数据结构不同
ArrayList是Array(动态数组)的数据结构,LinkedList是Link(链表)双向链表的数据结构。
2.2.空间灵活性
ArrayList其实最好需要指定初始容量的(当然有些程序员为了偷懒,根本不会去初始化,这其实对于代码质量低的项目而言是无关紧要的)
LinkedList是比ArrayList灵活的,是根本不需要指定初始容量的
2.3.线程安全性
ArrayList是线程不安全的,而LinkedList是线程安全的。
2.4.效率不同
当随机访问List(get和set操作)时,ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。ArrayList对于数据查询非常快,但是插入与删除元素比较慢;
当对数据进行增加和删除的操作(add和remove操作)时,LinkedList是恰好相反的,它的查询速度非常慢,但是插入与删除元素的速度非常快。
2.5.主要控件开销不同
ArrayList主要控件开销在于需要在lList列表预留一定空间;而LinkList主要控件开销在于需要存储节点信息以及节点指针。
3.Set集合的去重原理
先看元素的HashCode()值也就是哈希值是否相同,再看equals方法返回的结果
如果哈希值不同,则说明元素不相同,将元素添加到集合中
如果哈希值相同,则继续判断equals方法, 返回true则存入, false则丢弃
因此必须重写equals()和hashcode方法
4.简述TCP的三次握手和四次挥手
4.1.三次握手
4.2.四次挥手
等待2MSL的意义
-
保证客户端最后发送的ACK能够到达服务器,帮助其正常关闭
由于这个ACK报文段可能会丢失,使得处于LAST_ACK状态的服务器得不到对已发送FIN报文段的确认,从而会触发超时重传。服务器会重发FIN报文段,客户端能保证在2MSL时间内收到来自服务器的重传FIN报文段,从而客户端重新发送ACK应答报文段,并重置2MSL计数。
假如客户端不等待2MSL就之间进入CLOSE状态,那么服务器会一直处于LAST_ACK状态。
当客户端发起建立SYN报文段请求建立新的连接时,服务端会发送RST报文段给客户端,连接建立的过程就会被终止。
-
防止已失效的连接请求报文段出现在本连接中
TIME_WAIT等待的2MSL时间,确保本连接内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。
5.mysql数据库中内连接和外连接的区别
5.1.连接结果不同
内连接的连接结果仅包含符合连接条件的行,参与连接的两个表都必须符合连接条件;而外连接的连接结果不仅包含了符合连接条件的行,同时还包括不符合自身条件的行,其中还包括左外连接、右外连接以及全外连接。
5.2.注意事项不同
内连接需要注意区分在嵌套查询时使用的any以及all的区别;外连接不需要区分,左表和右表都不受限制,所有记录都显示,两个表不足的地方可用null进行填充。
6.SpringBoot当中有哪些方式把Bean注入IOC容器
spring创建bean对象的基本流程是先创建对应的BeanDefinition对象,然后在基于BeanDefinition对象来创建Bean对象,SpringBoot也是如此,只不过通过注解创建BeanDefinition对象的时机和解析方式不同而已。SpringBoot是通过ConfigurationClassPostProcessor这个BeanFactoryPostProcessor类来处理。
6.1.xml
1.使用xml的方式来声明Bean的定义,Spring容器在启动的时候会加载并解析这个xml,把bean装载到IOC容器当中。
在 ICO 容器被初始化的时候,会创建和配置所有 Bean。可以通过lazy-init
属性延迟初始化的 Bean,这样设置之后,Bean 的初始化就是在首次请求时而不是在启动时。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<import resource="引入其他bean xml配置文件" />
<bean id="bean标识" class="完全类型名称"/>
<alias name="bean标识" alias="别名" />
</beans>
[在配置完Bean之后,我们就要进行使用,其实使用方法很简单,只需要实例化IOC容器就行。而org.springframework.context.ApplicationContext接口代表了IOC容器。而实例化通常使用ClassPathXmlApplicationContext进行。实例化完成之后,使用getBean(“名称”)方法就行获取具体的Bean。具体代码如下
//获取带IOC容器,"services.xml", "daos.xml"为参数表示xml文件的地址,可以设置多个
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
//我们的对象现在都在Spring中管理了,我们要使用,直接去里面取出来即可,hello为需要创建的对象所在的类名,
Hello hello = (Hello) context.getBean("hello");
//或者使用
Hello hello = context.getBean("hello",Hello.Class);
参考链接:
(4条消息) Spring系列之xml中bean定义详解(-)_spring xml bean_azhou的代码园的博客-CSDN博客
(4条消息) 【Spring】:IOC容器通过 XML 方式依赖注入_ioc注入 xml_悦.L的博客-CSDN博客
(4条消息) spring面试常见问题_使用xml声明bean_@Java小白学习中的博客-CSDN博客
6.2.@ComponentScan
2.使用@ComponentScan注解来扫描声明了@Controller、@Service、@Repository、@Component注解的类。
用于类或接口上主要是指定扫描路径,spring会把指定路径下带有指定注解的类自动装配到bean容器里。会被自动装配的注解包括@Controller、@Service、@Component、@Repository等等。与ComponentScan注解相对应的XML配置就是context:component-scan/, 根据指定的配置自动扫描package,将符合条件的组件加入到IOC容器中;
@ComponentScan有如下常用属性:
basePackages和value:指定要扫描的路径(package),如果为空则以@ComponentScan注解的类所在的包为基本的扫描路径。
basePackageClasses:指定具体扫描的类。
includeFilters:指定满足Filter条件的类。
excludeFilters:指定排除Filter条件的类。
useDefaultFilters=true/false:指定是否需要使用Spring默认的扫描规则:被@Component, @Repository, @Service, @Controller或者已经声明过@Component自定义注解标记的组件;
参考链接:
(1条消息) Spring注解扫描:ComponentScan使用及原理详解_shepherd126的博客-CSDN博客
(4条消息) spring boot自动装配之@ComponentScan详解-CSDN博客
6.3.@Configuration
该注解用于类上,并且搭配@Bean
注解使该注解标识的方法变成由spring容器管理的Bean对象。每个方法上都会加上这样的一个Bean的注解,方法本身会返回一个对象。
@Configuration上面添加了@Component元注解,因此, @Configuration是支持组件扫描的(一般要添加context:component-scan/ ) ,它跟其他普通的Component一样也支持@Autowired/@Inject,如果@Configuration的类有一个构造函数,也支持构造函数自动注入。@Configuration 类不仅可以被扫描到,它自己也可以配置@ComponentScan注解去做组件扫描。
@Configuration
//做组件扫描
@ComponentScan("com.acme.app.services")
public class AppConfig {
// various @Bean definitions ...
}
3.使用@Configuration注解声明配置类,并使用@Bean注解实现Bean的定义,这种方法其实是xml配置方法的一种演变,是Spring迈入到无配置化时代的里程碑。
参考链接:
SpringBoot的@Configuration扫盲 - 知乎 (zhihu.com)
6.4.@Import
4.使用@Import注解,导入配置类或者普通的Bean
@Import注解提供了三种用法
a、@Import一个普通类 spring会将该类加载到spring容器中
b、@Import一个类,该类实现了ImportBeanDefinitionRegistrar接口,在重写的registerBeanDefinitions方法里面,能拿到BeanDefinitionRegistry bd的注册器,能手工往beanDefinitionMap中注册 beanDefinition
c、@Import一个类 该类实现了ImportSelector 重写selectImports方法该方法返回了String[]数组的对象,数组里面的类都会注入到spring容器当中(自动装配)
参考链接:
(1条消息) @Import注解详解_中年危机的老男人的博客-CSDN博客
(1条消息) @Import 注解使用及原理解析_Cison chen的博客-CSDN博客
6.5.FactoryBean
5.使用FactoryBean工厂bean,动态构建一个Bean实例,Spring Cloud OpenFeign里面的动态代理实例就是使用FactoryBean来实现的。
一般情况下,Spring 通过反射机制利用 bean 的 class 属性指定实现类来实例化 bean。
在某些情况下,实例化 bean 过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息,配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。
Spring 为此提供了一个 org.Springframework.bean.factory.FactoryBean 的工厂类接口,用户可以通过实现该接口定制实例化 bean 的逻辑。
参考链接:
(1条消息) 【Spring学习】FactoryBean的使用_factorybean如何使用_@来杯咖啡的博客-CSDN博客
6.6.ImportBeanDefinitionRegistrar
6.实现ImportBeanDefinitionRegistrar接口,可以动态注入Bean实例。这个在Spring Boot里面的启动注解有用到
刚才提到的@Import注解中的第二种方法就是设计的这个接口,我们可以传入一个实现了ImportBeanDefinitionRegistrar接口的类,spring会按照ImportBeanDefinitionRegistrar接口中的registerBeanDefinitions方法逻辑进行bean的注册。
参考链接:
Spring应用手册-ImportBeanDefinitionRegistrar接口 - 知乎 (zhihu.com)
ImportBeanDefinitionRegistrar接口是也是spring的扩展点之一,它可以支持我们自己写的代码封装成BeanDefinition对象;实现此接口的类会回调postProcessBeanDefinitionRegistry方法,注册到spring容器中。把bean注入到spring容器不止有 @Service @Component等注解方式;还可以实现此接口。
参考链接:
(1条消息) ImportBeanDefinitionRegistrar_愤怒的苹果ext的博客-CSDN博客
6.7.ImportSelector
7.实现ImportSelector接口,动态批量注入配置类或者Bean对象,这个在Spring Boot里面的自动装配机制里面有用到。
ImportSelector接口,收集需要导入的配置类,如果该接口的实现类同时实现EnvironmentAware, BeanFactoryAware ,BeanClassLoaderAware或者ResourceLoaderAware,那么在调用其selectImports方法之前先调用上述接口中对应的方法,如果需要在所有的@Configuration处理完再导入时可以实现DeferredImportSelector接口。
ortSelector接口,动态批量注入配置类或者Bean对象,这个在Spring Boot里面的自动装配机制里面有用到。
ImportSelector接口,收集需要导入的配置类,如果该接口的实现类同时实现EnvironmentAware, BeanFactoryAware ,BeanClassLoaderAware或者ResourceLoaderAware,那么在调用其selectImports方法之前先调用上述接口中对应的方法,如果需要在所有的@Configuration处理完再导入时可以实现DeferredImportSelector接口。
参考链接:
(1条消息) 死磕源码系列【ImportSelector接口原理解析】_importselector 原理_OceanSky6的博客-CSDN博客