各种问题以及解答(更新中)

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的意义
  1. 保证客户端最后发送的ACK能够到达服务器,帮助其正常关闭

    由于这个ACK报文段可能会丢失,使得处于LAST_ACK状态的服务器得不到对已发送FIN报文段的确认,从而会触发超时重传。服务器会重发FIN报文段,客户端能保证在2MSL时间内收到来自服务器的重传FIN报文段,从而客户端重新发送ACK应答报文段,并重置2MSL计数。

    假如客户端不等待2MSL就之间进入CLOSE状态,那么服务器会一直处于LAST_ACK状态。

    当客户端发起建立SYN报文段请求建立新的连接时,服务端会发送RST报文段给客户端,连接建立的过程就会被终止。

  2. 防止已失效的连接请求报文段出现在本连接中

    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博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值