java面试知识点

一、MySQL索引

mysql的索引分为单列索引(主键索引,唯索引,普通索引)和组合索引.

  单列索引:一个索引只包含一个列,一个表可以有多个单列索引.
          1.普通索引 create index
          2.唯一索引 所在列的值唯一但可以有null值不自增
          3.主键索引 自增唯一不允许空值

  组合索引:一个组合索引包含两个或两个以上的列,

         如果你建立了 组合索引(a_b_c_Index) 那么他实际包含的是3个索引 (a) (a,b)(a,b,c), 查询条件a和c使用的只是a的索引
  
  全文索引:有了全文索引,就可以用SELECT查询命令去检索那些包含着一个或多个给定单词的数据记录了。

索引的设计原则(不建索引情况)

   1、索引并非越多越好,索引会占用磁盘空间,还会影响增删改的性能,因为数据更改,索引也会进行调整和更新
   2、经常更新的表少建索引,查询字段建索引
   3、数据量少的不要建索引
   4、不同值少的列不要建索引,比如男女
   5、在查询条件中使用<>会导致索引失效。

创建索引
1、创建表的时候建索引,主键索引
2、做业务处理查询的时候创建索引

使用索引需要注意的地方

   1、在经常需要搜索的列上,可以加快索引的速度
   2、在表与表的而连接条件上加上索引,可以加快连接查询的速度
   3、在经常需要排序(order by),分组(group by)和的distinct 列上加索引 可以加快排序查询的时间
   4、like语句的,%前置索引不起作用
   5、索引不会包含NULL列,如果列中包含NULL值索引失效,复合索引中如果有一列含有NULL值那么这个组合索引都将失效,
   6、不要在列上进行运算,这样会使得mysql索引失效,也会进行全表扫描
   7、使用短索引

数据库优化

1、建索引、索引的注意事项以上几点
2、缓存
3、不要用select *
4、使用left join
5、分库分表分区、读写分离
6、查询一条limit 1
7、避免频繁创建和删除临时表,以减少系统表资源的消耗
8、Update 语句,如果只更改1、2个字段,不要Update全部字段
9、where子句代替having
10、explain查看执行过程

存储过程
存储过程Procedure是一组为了完成特定功能的SQL语句集合,经编译后存储在数据库中,用户通过指定存储过程的名称并给出参数来执行。

  CREATE PROCEDURE delete_matches(IN p_playerno INTEGER)
    -> BEGIN
    ->   DELETE FROM MATCHES
    ->    WHERE playerno = p_playerno;
    -> END

以上是创建,执行是 call delete_matches(57);

  1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般 SQL 语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。 
    2.当对数据库进行复杂操作时(如对多个表进行 Update,Insert,Query,Delete 时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。这些操作,如果用程序来完成,就变成了一条条的 SQL 语句,可能要多次连接数据库。而换成存储,只需要连接一次数据库就可以了。 
    3.存储过程可以重复使用,可减少数据库开发人员的工作量。 
    4.安全性高,可设定只有某此用户才具有对指定存储过程的使用权。

一分钟教你知道乐观锁和悲观锁的区别

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

5、sql的left join 、right join 、inner join之间的区别 左右表各有对方没有的行

     left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录,右边有null
  right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录,左边有null
  inner join(等值连接) 只返回两个表中联结字段相等的行,  左右表都不全,无null
       full jion   返回所有

二、springMVC执行流程

1、  用户发送请求至前端控制器DispatcherServlet。
  
2、  DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、  处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

4、  DispatcherServlet调用HandlerAdapter处理器适配器。

5、  HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

6、  Controller执行完成返回ModelAndView。

7、  HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。

8、  DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

9、  ViewReslover解析后返回具体View。

10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

11、 DispatcherServlet响应用户。

三、AOP和IoC(控制反转)和DI(依赖注入)

  IoC(控制反转):以前需要什么对象,自己就创建什么,但使用spring后创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题

     DI(依赖注入):属性注入、构造器注入、接口。常用属性可以配置<bean> 也可以使用resource注解autowire注解

3、spring AOP自定义注解方式实现日志管理
(1)创建日志类实体、 编写dao接口、service层
(2)自定义注解

    package com.gcx.annotation;

           import java.lang.annotation.*;

           @Target({ElementType.PARAMETER, ElementType.METHOD})  
           @Retention(RetentionPolicy.RUNTIME)  
           @Documented  
           public @interface Log {

               /** 要执行的操作类型比如:add操作 **/  
               public String operationType() default "";  

               /** 要执行的具体操作比如:添加用户 **/  
               public String operationName() default "";
            }
       (3)编写切面类,类里面的切入点@Pointcut("execution (* com.gcx.controller..*.*(..))")  或者@Pointcut("@annotation(注解类包名加类名)")
            环绕通知里写插入日志的代码@Around("controllerAspect()"),同时日志实体中操作名从注解中获取
             operationName = method.getAnnotation(Log.class).operationName();
                @Aspect
                @Component
                public class SystemLogAspect {
       (4)在其他controller操作方法上加自定义的注解
         @RequestMapping("testAOP")
         @Log(operationType="add操作:",operationName="添加用户") 

四、并发优化

1、加缓存
2、分库分表,读写分离
3、集群 负载均衡(nginx)
4、多线程,与当前主业务无关的放其他线程处理
5、全局变量
6、常用页面做成静态的,大图片分割
7、数据库优化

五、springBoot启动原理(环境切换)

 启动类上有注解@SpringBootApplication,是一个组合注解,但实际上重要的只有三个Annotation:

      @Configuration(@SpringBootConfiguration点开查看发现里面还是应用了@Configuration)配置bean
      @EnableAutoConfiguration     自动配置也就是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器
      @ComponentScan      包扫描
  
  自动配置幕后英雄:SpringFactoriesLoader
  借助于Spring框架原有的一个工具类:SpringFactoriesLoader的支持,@EnableAutoConfiguration可以智能的自动配置功效才得以大功告成!

  SpringFactoriesLoader属于Spring框架私有的一种扩展方案,其主要功能就是从指定的配置文件META-INF/spring.factories加载配置。

  所以,@EnableAutoConfiguration自动配置的魔法骑士就变成了:从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中

org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注@Configuration 的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。

深入探索SpringApplication执行流程

    (1)SpringApplication的静态run方法,那么,这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法。
      (2)在SpringApplication实例调用 initialize初始化的时候 ,加载META-INF/spring.factories路径ApplicationContextInitializer.class和ApplicationListener.class并实例化,就

是ApplicationContext和监听器实例化
      (3) 创建并配置当前Spring Boot应用将要使用的Environment
      (4)将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。

切换不同的环境application-dev.yml和application-prod.yml和application-test.yml
application.yml 中使用 spring.profiles.active=dev

六、事务的隔离级别、传播行为

 @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.
 声明式事务有注解和aop方式配置(就是定义方法名),基本上两种方法都用

 事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播。
 代码中methodA()方法嵌套调用了methodB()方法,methodB()的事务传播行为由@Transaction(Propagation=XXX)设置决定。这里需要注意的是methodA()并没有开启事务,某一个事务传播行为修饰的方法并不是必须要在开启事务的外围方法中调用。

事务传播行为类型 说明

PROPAGATION_REQUIRED	如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS	支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY	使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW	新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED	以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER	以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED	如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

情景:method A方法中调用了method B

  1. 单独调用methodB方法时,因为当前上下文不存在事务,所以会开启一个新的事务。 method A、B均为required
    调用methodA方法时,因为当前上下文不存在事务,所以会开启一个新的事务。当执行到methodB时,methodB发现当前上下文有事务,因此就加入到当前事务中来。
    2.method A为required、method B为supports
    单纯的调用methodB时,methodB方法是非事务的执行的。当调用methdA时,methodB则加入了methodA的事务中,事务地执行。
    3.method A为required、method B为mandatory
    当单独调用methodB时,因为当前没有一个活动的事务,则会抛出异常。当调用methdA时,methodB则加入了methodA的事务中,事务地执行。

    并发下事务会产生的问题
    1、脏读,就是指事务A读到了事务B还没有提交的数据
    2、不可重复读,就是指在一个事务里面读取了两次某个数据,读出来的数据不一致
    3、幻读,就是指在一个事务里面的操作中发现了未被操作的数据

    事务隔离级别,就是为了解决上面几种问题而诞生的。为什么要有事务隔离级别,因为事务隔离级别越高,在并发下会产生的问题就越少,但同时付出的性能消耗也将越大,因此很多时候必

须在并发性和性能之间做一个权衡。
事务隔离级别有4种,但是像Spring会提供给用户5种,

TRANSACTION_NONE JDBC驱动不支持事务 
TRANSACTION_READ_UNCOMMITTED 允许脏读、不可重复读和幻读。 
TRANSACTION_READ_COMMITTED 禁止脏读,但允许不可重复读和幻读。 
TRANSACTION_REPEATABLE_READ 禁止脏读和不可重复读,单运行幻读。 
TRANSACTION_SERIALIZABLE 禁止脏读、不可重复读和幻读。

可以在my.ini文件中使用transaction-isolation选项来设置服务器的缺省事务隔离级别。

七、Redis缓存

1、字符串 String
     1.GET、SET 和 DEL 
     2.INCR:就是 key 自增 1,不存在,自增后 get(key)=1;
       DECR:就是 key 自减 1,不存在,自减后返回 -1;
       INCRBY:自增 k ,不存在,则返回 k; DECRBY
2、哈希 Hash
     HGET、HSET、
3、列表 List
    常用命令有 LPUSH、RPUSH、LPOP、RPOP、LRANGE  
    LPUSH key value1 [value2]:将一个或多个值插入到列表头部;
        
RPUSH key value1 [value2]:在列表中添加一个或多个值;
        
LPOP key:移出并获取列表的第一个元素;
        
RPOP key:移除并获取列表最后一个元素;
        
LRANGE key start stop:获取列表指定范围内的元素。
     4、集合 Set
            常用命令有SADD、SCARD、SNENVERS、SPOP。
          SADD key member1:向集合添加一个或多个成员;
          SCARD key:获取集合的成员数;
          SMEMBERS key:返回集合中的所有成员;
          SPOP key:移除并返回集合中的一个随机元素。
     5、Sorted Set 有序集合
          Sorted Set 和 Set 最大的不同是前者是自动排序的,而后者是无序的。如果你需要一个有序的,但是不重复的数据结构的,就可以使用sorted set。

          常用的命令有 ZADD、ZRANGE、ZREM、ZCARD。
          ZADD key score1 member1:向有序集合添加一个或多个成员,或者更新已存在成员的分数;
          
ZRANGE key start stop:通过索引区间返回有序集合成指定区间内的成员;
          
ZREM key member:移除有序集合中的一个或多个成员;
          
ZCARD key:获取有序集合的成员数。
     6、Transactions 事务
       Redis 提供了 WATCH 命令,我们可以对某个 key 来 watch 一下,然后再执行 Transactions。如果这个被Watch 的值进行了修改,那么这个 Transactions 会发现并拒绝执行。
       常用命令有 MULTI、EXEC、DISCARD。


     设置过期时间expire

八、shiro

(1)使用用户的登录信息创建令牌
      UsernamePasswordToken token = new UsernamePasswordToken(username, password);
(2)执行登陆动作
       SecurityUtils.setSecurityManager(securityManager); // 注入SecurityManager
       Subject subject = SecurityUtils.getSubject(); // 获取Subject单例对象
       subject.login(token); // 登陆
(3)判断用户
     Shiro本身无法知道所持有令牌的用户是否合法,因为除了项目的设计人员恐怕谁都无法得知。因此Realm是整个框架中为数不多的必须由设计者自行实现的模块,也就是自定义realm extends AuthorizingRealm

根据Shiro的设计思路,用户与角色之前的关系为多对多,角色与权限之间的关系也是多对多。在数据库中需要因此建立5张表,分别是用户表(存储用户名,密码,盐等)、角色表(角色名称,相关描述等)、权限表(权限名称,相关描述等)、用户-角色对应中间表(以用户ID和角色ID作为联合主键)、角色-权限对应中间表(以角色ID和权限ID作为联合主键)。

九、JPA(hibernate)

Hibernate一级缓存是Session缓存,二级缓存是SessionFactory级的缓存。
总的来说,JPA是规范,Hibernate是框架,JPA是持久化规范,而Hibernate实现了JPA。
注解,实体类上 @Entity 和@Table(name=“tablename”)
实体类属性上 @Transient :标注此注解后在创建数据表的时候将会忽略该属性

十、dubbo

 RPC(Remote Procedure Call Protocol):远程过程调用: 

两台服务器A、B,分别部署不同的应用a,b。当A服务器想要调用B服务器上应用b提供的函数或方法的时候,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义传达调用的数据。

1.dubbo是面向服务治理的,维护方便,http少数接口调用主要用于接口测试。
2.httpclient是文本协议,适合短连接,dubbo支持长连接,这样避免了多次重复创建TCP连接的开销。 
3.使用dubbo不像httpclient一样json的转换,因为dubbo都自动进行了。

dubbo有一套自己的标签,提供给开发者配置,其实每一个标签对应着一个 实体,在容器启动的时候,dubbo会对所有的配置进行解析然后将解析后的内容设置到实体里,最终dubbo会根据实体中的值生成贯穿全局的统一URL。利用自定义标签使配置简单明了化,与spring完美融合。解析服务
 基于dubbo.jar内的META-INF/spring.handlers配置,Spring在遇到dubbo名称空间时,会回调DubboNamespaceHandler。
 所有dubbo的标签,都统一用自定义的DubboBeanDefinitionParser的parse()进行解析,基于一对一属性映射,将XML标签解析为Bean对象。并且自定义了ServiceBean和ReferenceBean继承了ServiceConfig
 在ServiceConfig.export()或ReferenceConfig.get()初始化时,将Bean对象转换URL格式,所有Bean属性转成URL的参数。
 然后将URL传给Protocol扩展点,基于扩展点的Adaptive机制,根据URL的协议头,进行不同协议的服务暴露或引用。

Provider: 暴露服务的服务提供方。

Consumer: 调用远程服务的服务消费方。

Registry: 服务注册与发现的注册中心。

Monitor: 统计服务的调用次数和调用时间的监控中心。

调用流程

0.服务容器负责启动,加载,运行服务提供者。

1.服务提供者在启动时,向注册中心注册自己提供的服务。

2.服务消费者在启动时,向注册中心订阅自己所需的服务。

3.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

4.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

5.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心

 使用dubbo不像httpclient一样json的转换,因为dubbo都自动进行了。

 今天遇到了一个问题,dubbo中有一个接口要提供出两个不同的实现作为服务
 提供者中需要有对应的组(group)来让zookeeper知道是两个服务:(使用group创建组)
 在web端需要也指定服务的group
 当一个接口有多种实现时,可以用 group 属性来分组,服务提供方和消费方都指定同一个 group 即可。

Dubbo 的服务容器只是一个简单的 Main 方法,并加载一个简单的 Spring 容器,用于暴露服务。

Dubbo 默认使用 Netty 框架,也是推荐的选择,另外内容还集成有Mina、Grizzly。

Dubbo 默认使用dubbo协议。缺省协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用。
序列化:Hessian 二进制序列化
使用dubbo要求传输的对象必须实现序列化接口Serializable

Dubbo服务之间的调用默认是同步等待结果阻塞的,支持异步调用。多版本用version

服务提供者能实现失效踢出基于zookeeper的临时节点原理。

 1.dubbo原理:先是解析服务就是将服务装载容器中,然后准备注册服务。所以dubbo也是先读配置文件解析服务。所有的dubbo标签,都统一用DubboBeanDefinitionParser进行解析,基于一对一属性映射,将XML标签解析为Bean对象。其中serviceBean继承了ServiceConfig。

 2. 接下来就是 Dubbo 服务暴露的过程。暴露调用的是:ServiceConfig.export() 

 首先ServiceConfig类拿到对外提供服务的实际类ref,然后将ProxyFactory类的getInvoker方法使用ref生成一个AbstractProxyInvoker实例,到这一步就完成具体服务到invoker的转化。接下来就是Invoker转换到Exporter的过程,Dubbo协议的Invoker转为Exporter发生在DubboProtocol类的export方法,它主要是打开socket侦听服务,并接收客户端发来的各种请求,通讯细节由dubbo自己实现。

3.服务消费的主过程: 
首先ReferenceConfig类的init方法调用Protocol的refer方法生成Invoker实例。接下来把Invoker转为客户端需要的接口即可。

 <!-- 应用名 -->
<dubbo:application name="dubbo-provider"/>

 <!-- 连接到哪个本地注册中心 -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>


 <!-- 协议配置,用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受  -->

 <dubbo:protocol name="dubbo" server="netty" port="20882" serialization="hessian2" />
   
 <!-- 监控中心配置,protocol="registry",表示从注册中心发现监控中心地址 
<dubbo:monitor protocol="registry"/>
-->
    <!-- 当ProtocolConfig和ServiceConfig某属性没有配置时,采用此缺省值 -->

 <dubbo:provider timeout="30000" threadpool="fixed" threads="100" accepts="1000" />

 <!-- 声明需要暴露的服务接口 -->

 <dubbo:service timeout="60000" interface="com.yangqi.service.UserService" ref="userService" protocol="dubbo"/>

 <!--具体实现该接口的 bean-->
<bean id="userService" class="com.yangqi.service.impl.UserServiceImpl"/>
 消费者是<dubbo:reference id="userService" interface="com.yangqi.service.UserService"/>

Dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止Spring初始化完成,以便上线时,能及早发现问题,默认check=true。可以通过check="false"关闭检查,比如,

测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。
关闭所有服务的启动时检查:(没有提供者时报错)dubbo:consumercheck=“false”/
dubbo:provider/ 提供方的缺省值,当ProtocolConfig和ServiceConfig某属性没有配置时,采用此缺省值,可选。
dubbo:consumer/ 消费方缺省配置,当ReferenceConfig某属性没有配置时,采用此缺省值,可选。

Dubbo内置支持如下6种集群模式:
     (1) Failover Cluster模式 cluster="failover"这种模式是Dubbo集群容错默认的模式选择,调用失败时,会自动切换,重新尝试调用其他节点上可用的服务。  retries=“2”控制调用次数
     (2) Failfast Cluster模式 这种模式称为快速失败模式,调用只执行一次,失败则立即报错。
     (3) Failsafe Cluster模式 失败安全模式,如果调用失败, 则直接忽略失败的调用,而是要记录下失败的调用到日志文件,以便后续审计。
     (4) Failback Cluster模式  失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
     (5) Forking Cluster模式  并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源
     (6) Broadcast Cluster模式 配置值为broadcast。广播调用所有提供者,逐个调用,任意一台报错则报错(2.1.0开始支持)。通常用于通知所有提供者更新缓存或日志等本地资源信息

十一、JVM(tomcat优化)

 Java代码执行过程:java源代码.java文件经编译器编译成字节码.class文件,类加载器把Java字节码载入到运行时数据区,执行引擎负责Java字节码的执行。

 JVM内存结构分为:方法区(method),栈内存(stack),堆内存(heap),本地方法栈(java中的jni调用)
    (1)堆内存(heap):所有通过new创建的对象
    (2)栈内存(stack):基础数据类型和对象的引用变量
 
 在tomcat的bin/catalina.bat文件的开头添加相关的配置

 栈是运行时的单位,而堆是存储的单位。

 栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;堆解决的是数据存储的问题,即数据怎么放、放在哪儿。

 在Java中一个线程就会相应有一个线程栈与之对应,这点很容易理解,因为不同的线程执行逻辑有所不同,因此需要一个独立的线程栈。而堆则是所有线程共享的。栈因为是运行单位,因此里面存储的信息都是跟当前线程(或程序)相关信息的。包括局部变量、程序运行状态、方法返回值等等;而堆只负责存储对象信息。

jvm调优没有一个固定模板配置说必须如何操作,它需要根据系统的情况不同对待。目前针对JVM的调优主要有两个方面:内存调优和垃圾回收策略调优。1.找到Tomcat根目录下的bin目录,设置catalina.sh文件中JAVA_OPTS变量即可,

 1、初始化内存和最大内存尽量保持一致,避免内存不够用继续扩充内存。最大内存不要超过物理内存,例如内存8g,你可以设置最大内存4g/6g但是不能超过8g否则加载类的时候没有空间会报错。

 2、gc/full gc频率不要太高、每次gc时间不要太长、根据系统应用来定。

 JVM配置方面,一般情况可以先用默认配置
 那么JVM的配置比如新生代、老年代应该配置多大最合适呢?答案是不一定,调优就是找答案的过程,物理内存一定的情况下,新生代设置越大,老年代就越小,Full GC频率就越高,但Full GC时间越短;相反新生代设置越小,老年代就越大,Full GC频率就越低,但每次Full GC消耗的时间越大。

-Xms和-Xmx的值设置成相等,堆大小默认为-Xms指定的大小,默认空闲堆内存小于40%时,JVM会扩大堆到-Xmx指定的大小;
新生代尽量设置大一些,让对象在新生代多存活一段时间,减少gc的次数

有如下原因可能导致Full GC:
     . 年老代(Tenured)被写满

     . 持久代(Perm)被写满

     . System.gc()被显式调用

     . 上一次GC之后Heap的各域分配策略动态变化

jvm参数在哪里设置
在哪里设置,分好几种情况:?

     1、集成开发环境下启动并使用JVM,如eclipse需要修改根目录文件eclipse.ini;?
         
2、Windows服务器下安装版Tomcat,可使用Tomcat7w.exe工具(tomcat目录下)和直接修改注册表两种方式修改Jvm参数;?
         
3、Windows服务器解压版Tomcat注册Windows服务,方法同上;?
         
4、解压版本的Tomcat, 通过startup.bat启动tomcat加载配置的,在tomcat 的bin 下catalina.bat 文件内添加;?
         
5、Linux服务器Tomcat设置JVM,修改TOMCAT_HOME/bin/catalina.sh;

tomcat优化配置参数
优化内存,主要是在bin/catalina.bat/sh 配置文件中进行设置 java_OPTS。

     1.Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,有可能导致系统无法运行。常见的问题是报Tomcat内存溢出错误,Outof Memory(系统内存不足)的异常,从而导致客户端显示500错误,一般调整Tomcat的-Xms和-Xmx即可解决问题,通常将-Xms和-Xmx设置成一样,堆的最大值设置为物理可用内存的最大值的80%。

     2.#优化连接数,主要是在conf/server.xml配置文件中进行修改。maxThreads="500"

Tomcat性能优化方案整理

 增加JVM堆内存大小  \bin\catalina.sh
    修复JRE内存泄漏    我们使用最新的tomcat版本6.0.26及以上就可以解决这个错误,因为它包含了一个监听器来处理JRE和PermGen的内存泄漏 /conf/server.xml   <Listener 

className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />  
    线程池设置        conf/server.xml 可以通过调整连接器属性“maxThreads”完成设置。
    压缩      server.xml配置文件中设置压缩的选项 设置属性compression="on" 否则当文件的大小大于等于500bytes时才会压缩
    数据库性能调优
    Tomcat本地库
    其它选项    开启浏览器的缓存,这样读取存放在webapps文件夹里的静态内容会更快,大大推动整体性能。
                每当开机时,Tomcat服务器应当自动地重启。
                一般情况下HTTPS请求会比HTTP请求慢。如果你想要更好的安全性,即使慢一点我们还是要选择HTTPS。

面试:“你知道GC吗”?、“你了解GC机制吗”? 作用,在什么时候,对谁,做了什么

   1. GC作用是在适当时候帮助回收JVM中的“垃圾”也就是GC会在什么时候触发,主要有以下几种触发条件:
   2.    执行System.gc()的时候:建议执行Full GC,但是JVM并不保证一定会执行

        新生代空间不足(下面会详细展开)分为一个Eden两个Survivor区

        老年代空间不足(下面会详细展开)

对象大都在Eden区分配内存,如果某个时刻JVM需要给某一个对象在Eden区上分配一块内存,但是此时Eden区剩余的连续内存小于该对象需要的内存,Eden区空间不足会触发minor GC。

触发minor GC前会检查之前每次Minor GC时晋升到老年代的平均对象大小是否大于老年代剩余空间大小,如果大于,则直接触发Full GC;否则,查看HandlePromotionFailure参数的值,如果为false,则直接触发Full GC;如果为true(默认为true,表示允许担保失败,虽然剩余空间大于之前晋升到老年代的平均大小,但是依旧可能担保失败),则仅触发Minor GC,如果期间发生老年代不足以容纳新生代存活的对象,此时会触发Full GC 。
进入老年代的对象:大对象直接进入老年代,长期存活的对象将进入老年代。老年代满了,会触发Full GC(回收整个堆内存)。

    所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。新生代发生的GC也叫做Minor GC,MinorGC发生频率比较高到老年代

    在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。当老年代内存满时触发Major GC即Full GC,

3.对不再使用的对象进行回收,怎么判别一个对象是否还活着呢?这时可以从“引用计数法”讲到“可达性分析算法”。

    (1. 引用计数法:给对象添加一个引用计数器,每当有地方引用它时,计数器加1;当引用失效时,计数器减1。引用计数法实现简单,判定效率高,但是它很难解决对象之间的互相循环引用(引用环问题)的问题。
    (2.可达性分析算法(主流实现判断对象是否“活着”算法):算法的基本思路就是以一系列的称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称 为引用链,当一个对象到GC Roots没有任何引用链相连的时候(即该对象不可达),则证明此对象是不可用的。

4.不可达的对象,如何被回收:

    (1)标记-清除法:在标记(可达性算法标记)完成后统一回收所有被标记的对象。它是最基础的算法,后续算法都是基于它的不足而改进,
             (2)复制算法:为了解决标记清除算法的效率问题,“复制算法”出现了。
             (3)标记-整理法:复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。
             (4)分代收集算法:JVM在实际垃圾回收中实际使用的是分代收集算法:根据对象存活周期的不同将内存划分为:新生代和老年代。在新生代每次都只有少量对象存活,选用复制算法;老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用标记-整理法或是标记-清理法进行回收。

    新生代收集器有:Serial收集器、ParNew收集器、Parallel Scavenge收集器;老年代收集器:Cocurrent Mark Sweep(CMS)收集器、Serial Old(MSC)收集器、Parallel Old收集器。另

外就是G1收集器,G1独自管理整个内存,不再分新生代和老年代了。

   tomcat的bin/catalina.sh设置JAVA_opts可以设置
   -Xmx512m:设置JVM最大可用内存为512M;
   -Xms512m:设置JVM启动时堆的初始化大小。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。

   -XX:+PrintGC :输出GC日志

输出形式:

        [GC 118250K->113543K(130112K), 0.0094143 secs]
        [Full GC 121376K->10414K(130112K), 0.0650971 secs]


   -XX:+PrintGCDetails :输出GC的详细日志

5.tomcat部署web应用的4种方法

第一种方式:利用Tomcat自动部署
 第二种方式:利用控制台进行部署
 第三种方式:增加自定义的Web部署文件
 第四种方式:手动修改%Tomcat_Home%\conf\server.xml文件来部署web应用

十二、消息队列 rabbit mq
RabbitMQ是一个实现了AMQP(Advanced Message Queuing Protocol)高级消息队列协议的消息队列服务,用Erlang语言的。

   1.消费者与生存者都需要声明队列
   2.发送完后需要断开连接
   3.这种一对一的模式我们称为:Simple模式

work一对多模式
1.怎样保证消息不因消费者gg而丢失?取消自动回复机制

  channel.basicConsume(QUEUE_NAME, true, consumer);

自动恢复机制默认是打开的,在接收端的代码最后:第二个参数为true,表示会自动回复,只要生产发送消息,就会标记删除。所以我们需要将自动回复设置为false。

  boolean autoAck = false;
       channel.basicConsume(QUEUE_NAME, autoAck, consumer);

那么取消自动回复以后,我们需要手动回复一次:

 channel.basicAck(envelope.getDeliveryTag(), false);

2.怎样保证消息不因生产者gg而丢失?消息持久化

 ①首先:从queue角度标记为持久化boolean durable = true;
          channel.queueDeclare("task_queue", durable, false, false, null);
          ②从message的角度标记持久化 
          channel.basicPublish("", "task_queue",MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes());

3.怎样实现消息的均匀分配?单个处理原则
int prefetchCount = 1;是指每次从Queue中发送一条消息来。等消费者处理完这条消息后Queue会再发送一条消息给消费者。
channel.basicQos(prefetchCount );// 负载均衡,指该消费者在接收到队列里的消息但没有返回确认结果之前,它不会将新的消息分发给它。
生产者:

public static void main(String[] args) throws IOException, TimeoutException {	
	
//实例化工厂
	
ConnectionFactory factory = new ConnectionFactory();
	
//设置相关参数,地址,端口,账号,密码
	
factory.setHost("localhost");
	
factory.setPort(5672);
	
factory.setUsername("guest");
	
factory.setPassword("guest");
	
//获取connection
	
Connection conn = factory.newConnection();
	
//获取channel
	
Channel channel = conn.createChannel();
	
    //创建队列	1-队列名称	2-队列是否持久化 3-是否是排他队列 4-使用完之后是否删除此队列	5-其他属性
		        
    channel.queueDeclare("hello", false, false, false, null);
//队列声明		
    //创建路由		1-路由名称	2-路由类型
		
    channel.exchangeDeclare("myexchange", "topic");
//简单队列无需创建路由,默认路由是队列名,routingkey无		
    //绑定路由队列	1-队列名称	2-路由名称	3-routing key		
		
    channel.queueBind("hello", "myexchange", "shensha");
		
    //发送消息		1-路由名称	2-routing key	3-其他信息	4-消息字节数组
		
    channel.basicPublish("myexchange", "shensha", null, "HelloWorld".getBytes());
		
    //关闭资源
	
channel.close();
	
conn.close();

}
消费者

public static void main(String[] args) {
	
// 实例化工厂
	
ConnectionFactory factory = new ConnectionFactory();
	
// 设置相关参数,地址,端口,账号,密码
	
factory.setHost("localhost");
	
factory.setPort(5672);
	
factory.setUsername("guest");
	
factory.setPassword("guest");
	
try {
		
    // 获取connection
		
    Connection conn = factory.newConnection();
		
    // 获取channel
		
    Channel channel = conn.createChannel();
		
    // 创建队列 1-队列名称 2-队列是否持久化 3-是否是排他队列 4-使用完之后是否删除此队列 5-其他属性
		        
    channel.queueDeclare("hello", false, false, false, null);
		
    //消费消息.	1-消费队列	2-是否自动发送消息回执	3-回调函数
		
    channel.basicConsume("hello", true, new DefaultConsumer(channel){
			
			     @Override
			
         public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
					throws 

IOException {
					
             String message = new String(body, "UTF-8");
				
             System.out.println("接收到的消息为: " + message);
			
         }
			
		
     });
	
} catch (Exception e) {
		
    e.printStackTrace();
	
}

}

常用的交换机类型有 3 种:fanout、direct、topic。
在绑定(Binding)Exchange和Queue的同时,一般会指定一个Binding Key,生产者将消息发送给Exchange的时候,一般会产生一个Routing Key,当Routing Key和Binding Key对应上的时候,消息就会发送到对应的Queue中去。
producer绑定exchange是routingkey, exchage到queue是bindingkey
fanout类型的Exchange路由规则非常简单,它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中。
direct类型的Exchange路由规则也很简单,它会把消息路由到那些binding key与routing key完全匹配的Queue中

  topic  前面提到的direct规则是严格意义上的匹配,那么topic这个规则就是模糊匹配,可以通过通配符满足一部分规则就可以传送。
  1.binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(或零个)
  2.binding key与routing key一样也是句点号“. ”分隔的字符串
  headers类型的Exchange不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。

1、简单队列一对一,work队列一对多,都是默认exchange
Work模式的“能者多劳”如果不设置两个消费者获取的消息相等是轮流分发的,对消费能力强的不公平
// 同一时刻服务器只会发一条消息给消费者

   channel.basicQos(1);
  //开启这行 表示使用手动确认模式

  channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  同时改为手动确认:

// 监听队列,false表示手动返回完成状态,true表示自动

channel.basicConsume(QUEUE_NAME, false, consumer);

2、订阅模式:消息发送到没有队列绑定的交换机时,消息将丢失,因为,交换机没有存储消息的能力,消息只能存在在队列中。
1、个生产者,多个消费者
2、每一个消费者都有自己的一个队列
3、生产者没有将消息直接发送到队列,而是发送到了交换机
4、每个队列都要绑定到交换机
5、生产者发送的消息,经过交换机,到达队列,实现,一个消息被多个消费者获取的目的

3、路由模式
Spring-Rabbit项目
用配置文件完成声明,绑定,rabbit:标签
Springboot集成RabbitMQ
1、配置pom文件,主要是添加spring-boot-starter-amqp的支持
2、配置application.properties文件
3、配置队列,生产者,消费者
消费者@Component

@RabbitListener(queues = “q_hello”)

           public class HelloReceiver {


               @RabbitHandler

               public void process(String hello) {
    
                   System.out.println("Receiver  : " + hello);

               }

}

十三、mybatis

MyBatis的初始化的过程其实就是解析配置文件和初始化Configuration的过程,首先会创建SqlSessionFactory建造者对象,然后由它进行创建SqlSessionFactory。(这里用到的是建造者模式,建造者模式最简单的理解就是不手动new对象,而是由其他类来进行对象的创建。)
然后,SqlSessionFactory的实例直接开启一个SqlSession,再通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交,之后关闭SqlSession。

十四、spring bean 生命周期

找工作的时候有些人会被问道Spring中Bean的生命周期,其实也就是考察一下对Spring是否熟悉,工作中很少用到其中的内容,那我们简单看一下。

在说明前可以思考一下Servlet的生命周期:实例化,初始init,接收请求service,销毁destroy;

spring bean
      容器中Bean的作用域:singleton 和 prototype, request,session,global session共五种
      对于singleton作用域,每次请求该Bean都将获得相同的实例,客户端代码不能控制Bean的销毁,它的生命周期都在Spring的掌握之中。这么一来,容器就可以管理实例化结束后(某些资源的申请)和销毁之前(进行某些资源的回收)的行为。管理Bean的生命周期行为主要有两个时机:注入依赖关系后,销毁实例之前;
      设置成prototype作用域,每次请求Spring都会创建一个新的Bean实例

Spring上下文中的Bean也类似,如下

  1、实例化一个Bean--也就是我们常说的new;

    2、按照Spring上下文对实例化的Bean进行配置--也就是IOC注入;

    3、如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值

    不需要4、如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(可以用这个方式来获取其它Bean,只需

在Spring配置文件中配置一个普通的Bean就可以);

    5、如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更

好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法);

    6、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这

个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术;

    7、如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。

    8、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法、;

    注:以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非

Singleton,这里我们不做赘述。

    9、当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;

    10、最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。

 

以上10步骤可以作为面试或者笔试的模板,另外我们这里描述的是应用Spring上下文Bean的生命周期,如果应用Spring的工厂也就是BeanFactory的话去掉第5步就Ok了。

2.BeanFactory 接口和 ApplicationContext 接口有什么区别 ?

       ①ApplicationContext 接口继承BeanFactory接口,Spring核心工厂是BeanFactory ,BeanFactory采取延迟加载,第一次getBean时才会初始化Bean, ApplicationContext是会在加载配置文件时初始化Bean。
           ②ApplicationContext是对BeanFactory扩展,它可以进行国际化处理、事件传递和bean自动装配以及各种不同应用层的Context实现 
开发中基本都在使用ApplicationContext, web项目使用WebApplicationContext ,很少用到BeanFactory

十五、jsp和servlet

  每个JSP 页面在第一次被访问时,JSP引擎将它翻译成一个Servlet源程序,接着再把这个Servlet源程序编译成Servlet的class类文件,然后再由WEB容器(Servlet引擎)像调用普通Servlet程序一样的方式来装载和解释执行这个由JSP页面翻译成的Servlet程序。

JSP的执行过程主要可以分为以下几点:

  客户端发出请求。

  Web容器将JSP转译成Servlet源代码。

  Web容器将产生的源代码进行编译。

  Web容器加载编译后的代码并执行。

  把执行结果响应至客户端。

在Servlet产生到消亡的过程中,有三个生命周期函数,构造方法实例化,初始化方法init(),处理客户请求的方法service(),终止方法destroy()。
十六、Spring工作原理

内部最核心的就是IOC了,
动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射?
反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,跟xml Spring的配置文件来动态的创建对象,和调用对象里的方法的 。
IOC 控制反转 概念:控制权由对象本身转向容器;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系

十七、反射、动态代理

过滤器和拦截器的区别:
①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

十八、spring cloud

  第一步:启动注册中心;服务提供者及调用者向服务中心注册; 
  第二步:服务调用者向服务中心申请服务,根据服务中心返回的地址信息调用服务提供者提供的服务; 
  第三步:注册中心通过心跳检测方式检测服务提供者的状态,当某个提供者连接不上时,发送消息通知所有注册者;

(1) Eureka服务端:在启动类加@EnableEurekaServer来表明节点是服务端。启动
# 以下两项一定要是false,表明自己是服务器,而不需要从其他主机发现服务
client: registerWithEureka: false
client: fetchRegistry: false
(2)服务提供方:在启动类加@EnableEurekaClient注册表明其是EurekaClient;
该注解会使得应用向EurekaServer进行注册,同时获取EurekaServer上所注册的所有应用信息; 这些注册信息通过自动注入的EurekaClient类可以获取到。@Autowired
private EurekaClient client;
(3) 服务调用方@Autowired // 通过EurekaClient调用
private EurekaClient client;
InstanceInfo instanceInfo = client.getNextServerFromEureka(“SERVICEAPP1”, false);

   通过Ribbon调用服务 引入依赖    @SpringBootApplication @EnableDiscoveryClient  通过RestTemplate来调用
   通过Feign调用服务  引入依赖  @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients  RemoteClient类来调用

十九、docker

 Docker 是 Docker Inc 公司开源的一项基于 Ubuntu LXC 技术之上构建的应用打包运行时引擎
 Docker 技术解决以下问题: 复杂的环境配置管理:从各种 OS 环境到各种中间件环境以及各种应用环境。
 在软件行业中任何应用要做到成功发布,开发团队需要关心的东西太多且难于统一管理,这个问题普遍存在并需要直接面对。Docker 技术旨在简化部署多种应用实例环境依赖,如 Web 应用、后台应用、数据库应用、大数据应用(例如Hadoop集群)、消息队列(例如Kafka)等等都可以打包成一个镜像部署。

二十、Linux

 1、  ls 的作用是列出当前目录下的文件。
 2、  mkdir 新建目录
 3、  touch 创建文件    touch test/readme.txt   在 test 目录下创建 readme.txt文件
 4、  cd 命令切换目录
 5、  pwd 显示当前目录
 6、  mv 命令移动文件    s3637077 文件移动到 workspace 目录下   mv s3637077 workspace/    还可以给文件重命名
 7、  cp 复制文件
 8、  rm 删除文件
 9、  zip target.zip filename  压缩文件
 10、 ifconfig 查看本机网路
 11、 vim   编辑
 12、 grep '05/Dec/2017' 查看日志

二十一、单例模式

二十二、ArrayList

  int newCapacity = oldCapacity + (oldCapacity >> 1),所以 ArrayList 每次扩容之后容量都会变为原来的 1.5 倍! 记清楚了!不是网上很多人说的 1.5 倍+1!

我们再来通过例子探究一下grow() 方法 :

当add第1个元素时,oldCapacity 为0,经比较后第一个if判断成立,newCapacity = minCapacity(为10)。但是第二个if判断不会成立,即

newCapacity 不比 MAX_ARRAY_SIZE大,则不会进入 hugeCapacity 方法。数组容量为10,add方法中 return true,size增为1。
当add第11个元素进入grow方法时,newCapacity为15,比

minCapacity(为11)大,第一个if判断不成立。新容量没有大于数组最大size,不会进入hugeCapacity方法。数组容量扩为15,add方法中return true,size增为11。
以此类推······

二十三、 Java中的值传递和引用传递(非常重要)

   值传递是指对象被值传递,意味着传递了对象的一个副本,即使副本被改变,也不会影响源对象。(因为值传递的时候,实际上是将实参的值复制一份给形参。)


   引用传递是指对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对象的改变会反映到所有的对象上。(因为引用传递的时候,实际上是将实参的地址值复制一份给形参。)

二十四、==与equals(重要)

   == : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。基本数据类型==比较的是值,引用数据类型==比较的是内存地址

  equals() : 它的作用也是判断两个对象的内容相等

  hashCode()与equals()的相关规定:
     如果两个对象相等,则hashcode一定也是相同的

     两个对象相等,对两个对象分别调用equals方法都返回true

     两个对象有相同的hashcode值,它们也不一定是相等的
     因此,equals方法被覆盖过,则hashCode方法也必须被覆盖

二十五、java Date和 Calendar 区别

  Calendar是日历
  Date是时间
  Date用来表示当前时间,通常是用来单纯的记录一个时间,它提供的api也非常少
  而Calendar则有非常多的api,
  Date用于记录某一个含日期的、精确到毫秒的时间。重点在代表一刹那的时间本身。
  Calendar用于将某一日期放到历法中的互动——时间和年、月、日、星期、上午、下午、夏令时等这些历法规定互相作用关系和互动。

二十六、线程

 什么是线程安全和线程不安全?
    线程安全: 就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问,直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。通俗的说:加锁的就是是线程安全的,不加锁的就是是线程不安全的

 JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)

 java堆(Java Heap)   可通过参数 -Xms 和-Xmx设置
       Java堆是被所有线程共享,是Java虚拟机所管理的内存中最大的一块 Java堆在虚拟机启动时创建。
       Java堆唯一的目的是存放对象实例,几乎所有的对象实例和数组都在这里。
       Java堆为了便于更好的回收和分配内存,可以细分为:新生代和老年代;再细致一点的有Eden空间、From Survivor空间、To Survivor区。
       新生代:包括Eden区、From Survivor区、To Survivor区,系统默认大小Eden:Survivor=8:1:1。
       老年代:在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。

二十七、java新特性

JDK1.8新特性
     主要特性有:

               接口的默认方法
               Lambda 表达式
               函数式接口
               方法与构造函数引用
               Lambda 作用域
               访问局部变量
               访问对象字段与静态变量
               访问接口的默认方法
               Date API
               Annotation 注解
   
JDK1.9新特性
     主要特性有:
                 模块化系统
、jShell命令
、多版本兼容jar包
、接口的私有方法
                 
钻石操作符的使用升级
、语法改进:try语句
、下划线使用限制
                 
String存储结构变更
便利的集合特性:of()
、增强的Stream API
多分辨率图像 API
                 
全新的HTTP客户端API、
Deprecated的相关API
、智能Java编译工具
                 
统一的JVM日志系统、
javadoc的HTML 5支持
、Javascript引擎升级:Nashorn

             java的动态编译器

JDK1.10新特性
      var 局部变量类型推断、统一的垃圾回收接口。
      将原来用 Mercurial 管理的众多 JDK 仓库代码,合并到一个仓库中,简化开发和管理过程。
      G1 垃圾回收器的并行完整垃圾回收,实现并行性来改善最坏情况下的延迟

TCP协议是面向连接的、可靠的传输层协议,规定了数据在网络中是如何传输的。通信前要先建立连接(三次握手机制)

   Socket和ServerScoket,建立客户端和服务端,建立连接后通过socket的IO流进行数据传输。通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值