线程
是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
线程是程序中一个单一的顺序控制流程。进程内有一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指令运行时的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。
//sleep wait 数据库锁
两种方式
继承 Thread类 实现Runnable 接口
Start 开启线程
Run 执行方法
Synchronous 同步代码块 同步方法 在多个线程共享数据时使用 解决安全问题
Wait 枷锁
Notify 开锁
死锁是怎样产生的
死锁是由于资源共享时,多个线程抢用一个资源时产生的,若无外力帮助,进程将永远不能执行
解决方法:
线程和进程的区别
1)地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
2)通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
3)调度和切换:线程上下文切换比进程上下文切换要快得多。
4)在多线程OS中,线程不是一个可执行的实体。
,队列优先,先进先出(FIFO—first in first out) [1] 。栈,先进后出(FILO—First-In/Last-Out)。
堆;一种特殊的数据结构的统称,可以被看作一棵树
一种完全二叉树,; 堆中的某个节点总是小于或者大于他的父节点
先画出完全二叉树结构,判断是否满足 最大堆:左右孩子都比父节点小 最小堆:左右孩子都比父节点大 |
堆是一种序列,总是满足(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4...n/2)
比如 1,2,8,4,3,9,10,5
数据结构
栈 : 一种先进后出的数据结构栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。栈也称为后进先出表。
队列: 队列是一种特殊的线性表,他只允许前端进行删除操作,后端进行插入操作,插入操作叫队尾,删除操作叫对头.
没有数据的队列叫空队列
建立顺序队列结构必须为其静态分配或动态申请一片连续的存储空间,并设置两个指针进行管理。一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队元素的存储位置。
不存在溢出问题,先进先出
Java 中 堆栈 队列
使用Deque线性表接口,可以在两端插入删除数据Deque接口提供的方法就可以完成队列“先进先出”和堆栈“后进先出”的功能:
队列 offer(E e) –向队列尾部加入元素
E poll() 获取头部元素,并从队列中删除
堆栈 push() 向队列中压入元素
E pop() 获取站定元素,并删除
Deque是个接口,其实现类有:
- ArrayDeque,使用“数组”存储数据
- LinkedList,使用“链表”存储数据
- ConcurrentLinkedDeque,线程安全的LinkedList
链表结构 (单链表 双链表 有序列表)
链表是一种物理存储单元上非连续非顺序的存储结构.数据元素的连接顺序是由指针链接次序实现的.链表由一系列的节点(存储的每一个元素)组成.节点在运行是动态生成
单链表 A知道B的位置 B知道C的位置….
双链表 B知道A的位置并且知道C的位置
有序链表 某个标准,给链表的元素排序,比如比较内容大小、比较哈希值等
二叉树
者为空,或者是由一个根节点加上两棵分别称为左子树和右子树的、互不相交的二叉树组成。
满二叉树 二叉树中所有分支节点的度数都为2 并且叶子(最下层的节点没有子元素)在同一层
完全二叉树 如果一棵具有n个结点的高度为k的二叉树,树的每个结点都与高度为k的满二叉树中编号为1——n的结点一一对应,则二叉树为完全二叉树。
完全二叉树的特性:
A、同样结点数的二叉树,完全二叉树的高度最小
B、完全二叉树的叶子结点仅出现在最下边两层,并且最底层的叶子结点一定出现在左边,倒数第二层的叶子结点一定出现在右边。
C、完全二叉树中度为1的结点只有左孩子。
遍历方式:
前序遍历 1.访问根节点 2. 先序遍历左子树 4.先序遍历右子树
1 2 4 8 9 5 10 3 6 7
中序遍历 中序遍历左子树 访问根节点 中序遍历右节点
8 4 9 2 10 5 1 6 3 7
后序遍历 后序遍历左子树 后序遍历右子树 访问根结点。
8 9 4 10 5 2 6 7 3 1
Hashmap linklist array
checked exception:指的是编译时异常,该类异常需要本函数必须处理的,用try和catch处理,或者用throws抛出异常,然后交给调用者去处理异常。
runtime exception:指的是运行时异常,该类异常不必须本函数必须处理,当然也可以处理。
Thread.sleep()抛出的InterruptException属于checked exception;IllegalArgumentException属于Runtime exception;
DBMS 中实现事务持久性的子系统是() 恢复管理子系统 (要想持久性管理,必须在出错时恢复)
会话跟踪 session cookie 隐藏域 地址重写
Spring mvc 处理Ajax 中put请求问题
/**
* 如果直接发送ajax=PUT形式的请求
* 封装的数据
* Employee
* [empId=1014, empName=null, gender=null, email=null, dId=null]
*
* 问题:
* 请求体中有数据;
* 但是Employee对象封装不上;
* update tbl_emp where emp_id = 1014;
*
* 原因:
* Tomcat:
* 1、将请求体中的数据,封装一个map。
* 2、request.getParameter("empName")就会从这个map中取值。
* 3、SpringMVC封装POJO对象的时候。
* 会把POJO中每个属性的值,request.getParamter("email");
* AJAX发送PUT请求引发的血案:
* PUT请求,请求体中的数据,request.getParameter("empName")拿不到
* Tomcat一看是PUT不会封装请求体中的数据为map,只有POST形式的请求才封装请求体为map
* org.apache.catalina.connector.Request--parseParameters() (3111);
*
* protected String parseBodyMethods = "POST";
* if( !getConnector().isParseBodyMethod(getMethod()) ) {
success = true;
return;
}
*
*
* 解决方案;
* 我们要能支持直接发送PUT之类的请求还要封装请求体中的数据
* 1、配置上HttpPutFormContentFilter;
* 2、他的作用;将请求体中的数据解析包装成一个map。
* 3、request被重新包装,request.getParameter()被重写,就会从自己封装的map中取数据
* 员工更新方法
* @param employee
* @return
*/
SSM Maven 下整合笔记
- 新建maven 项目 并在 pom.xml中引入需要的包
- Spring的相关配置applicationContext.xml
- 开启自动扫描组件
<context:component-scan base-package="com.cws">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" /> </context:component-scan>
(2)Spring配置数据库连接池采用c3p0连接池
<context:property-placeholder location="classpath:dbconfig.properties" />
<bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ssm_crud?useUnicode=true&characterEncoding=utf8"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
(3)Mybatis注入连接池 并将mapper 相关的管理绑定
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="dataSource" ref="pooledDataSource"></property>
<!-- 指定mybatis,mapper文件的位置 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
</bean>
(4).配置扫描器,将mybatis接口实现注入ioc容器
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--扫描所有dao接口的实现,加入到ioc容器中 -->
<property name="basePackage" value="com.cws.dao"></property>
</bean>
(5)Spring的事务管理(切入点,事务增强)
<!--切入点设置 -->
<aop:config>
<aop:pointcut expression="execution(* com.cws.service..*(..))"
id="txPointcut" />
<aop:advisor advice-ref="txadvice" pointcut-ref="txPointcut" />
</aop:config>
<!-- 事务增强 *代表所有方法 -->
<tx:advice id="txadvice">
<tx:attributes>
<tx:method name="*" />
<tx:method name="get*" read-only="true" />
</tx:attributes>
</tx:advice>
二, mybatis-config.xml的配置
主要开启驼峰命名 别名处理器等 其他数据库连接在Spring中处理
三,SpringMvc的配置
在web.xml中springmvc的前端控制器,拦截所有请求,放入同意目录下并保证名字为servlet-name-servlet.xml
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
dispatcherServlet-servlet.xml,
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--SpringMVC的配置文件,包含网站跳转逻辑的控制,配置 -->
<context:component-scan base-package="com" use-default-filters="false">
<!--只扫描控制器。 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--配置视图解析器,方便页面返回 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--两个标准配置 -->
<!-- 将springmvc不能处理的请求交给tomcat -->
<mvc:default-servlet-handler/>
<!-- 能支持springmvc更高级的一些功能,JSR303校验,快捷的ajax...映射动态请求 -->
<mvc:annotation-driven/>
Java 的屏幕坐标是以像素为单位,容器的左上角被确定为坐标的起点。
1.final修饰变量,则等同于常量
2.final修饰方法中的参数,称为最终参数。
3.final修饰类,则类不能被继承
4.final修饰方法,则方法不能被重写。
方法重载(overload):
1.必须是同一个类
2方法名(也可以叫函数)一样
3参数类型不一样或参数数量不一样
方法的重写(override)两同两小一大原则:
方法名相同,参数类型相同
子类返回类型小于等于父类方法返回类型,
子类抛出异常小于等于父类方法抛出异常,
子类访问权限大于等于父类方法访问权限
抽象类和接口的区别
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然
eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
5. 抽象类中可以包含静态方法,接口中不能包含静态方法
6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
7. 一个类可以实现多个接口,但只能继承一个抽象类。
ThreadLocal 线程局部变量
1、ThreadLocal的类声明:
public class ThreadLocal<T>
可以看出ThreadLocal并没有继承自Thread,也没有实现Runnable接口。所以AB都不对。
2、ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量。
所以ThreadLocal重要作用并不在于多线程间的数据共享,而是数据的独立,。
由于每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,不会被其他线程访问,变量被彻底封闭在每个访问的线程中。\
规范化解决了数据冗余,更新异常,插入异常,删除异常四个问题
线程
是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
线程是程序中一个单一的顺序控制流程。进程内有一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指令运行时的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。
//sleep wait 数据库锁
两种方式
继承 Thread类 实现Runnable 接口
Start 开启线程
Run 执行方法
Synchronous 同步代码块 同步方法 在多个线程共享数据时使用 解决安全问题
Wait 枷锁
Notify 开锁
死锁是怎样产生的
死锁是由于资源共享时,多个线程抢用一个资源时产生的,若无外力帮助,进程将永远不能执行
解决方法:
线程和进程的区别
1)地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
2)通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
3)调度和切换:线程上下文切换比进程上下文切换要快得多。
4)在多线程OS中,线程不是一个可执行的实体。
,队列优先,先进先出(FIFO—first in first out) [1] 。栈,先进后出(FILO—First-In/Last-Out)。
堆;一种特殊的数据结构的统称,可以被看作一棵树
一种完全二叉树,; 堆中的某个节点总是小于或者大于他的父节点
先画出完全二叉树结构,判断是否满足 最大堆:左右孩子都比父节点小 最小堆:左右孩子都比父节点大 |
堆是一种序列,总是满足(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4...n/2)
比如 1,2,8,4,3,9,10,5
数据结构
栈 : 一种先进后出的数据结构栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。栈也称为后进先出表。
队列: 队列是一种特殊的线性表,他只允许前端进行删除操作,后端进行插入操作,插入操作叫队尾,删除操作叫对头.
没有数据的队列叫空队列
建立顺序队列结构必须为其静态分配或动态申请一片连续的存储空间,并设置两个指针进行管理。一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队元素的存储位置。
不存在溢出问题,先进先出
Java 中 堆栈 队列
使用Deque线性表接口,可以在两端插入删除数据Deque接口提供的方法就可以完成队列“先进先出”和堆栈“后进先出”的功能:
队列 offer(E e) –向队列尾部加入元素
E poll() 获取头部元素,并从队列中删除
堆栈 push() 向队列中压入元素
E pop() 获取站定元素,并删除
Deque是个接口,其实现类有:
- ArrayDeque,使用“数组”存储数据
- LinkedList,使用“链表”存储数据
- ConcurrentLinkedDeque,线程安全的LinkedList
链表结构 (单链表 双链表 有序列表)
链表是一种物理存储单元上非连续非顺序的存储结构.数据元素的连接顺序是由指针链接次序实现的.链表由一系列的节点(存储的每一个元素)组成.节点在运行是动态生成
单链表 A知道B的位置 B知道C的位置….
双链表 B知道A的位置并且知道C的位置
有序链表 某个标准,给链表的元素排序,比如比较内容大小、比较哈希值等
二叉树
者为空,或者是由一个根节点加上两棵分别称为左子树和右子树的、互不相交的二叉树组成。
满二叉树 二叉树中所有分支节点的度数都为2 并且叶子(最下层的节点没有子元素)在同一层
完全二叉树 如果一棵具有n个结点的高度为k的二叉树,树的每个结点都与高度为k的满二叉树中编号为1——n的结点一一对应,则二叉树为完全二叉树。
完全二叉树的特性:
A、同样结点数的二叉树,完全二叉树的高度最小
B、完全二叉树的叶子结点仅出现在最下边两层,并且最底层的叶子结点一定出现在左边,倒数第二层的叶子结点一定出现在右边。
C、完全二叉树中度为1的结点只有左孩子。
遍历方式:
前序遍历 1.访问根节点 2. 先序遍历左子树 4.先序遍历右子树
1 2 4 8 9 5 10 3 6 7
中序遍历 中序遍历左子树 访问根节点 中序遍历右节点
8 4 9 2 10 5 1 6 3 7
后序遍历 后序遍历左子树 后序遍历右子树 访问根结点。
8 9 4 10 5 2 6 7 3 1
Hashmap linklist array
checked exception:指的是编译时异常,该类异常需要本函数必须处理的,用try和catch处理,或者用throws抛出异常,然后交给调用者去处理异常。
runtime exception:指的是运行时异常,该类异常不必须本函数必须处理,当然也可以处理。
Thread.sleep()抛出的InterruptException属于checked exception;IllegalArgumentException属于Runtime exception;
DBMS 中实现事务持久性的子系统是() 恢复管理子系统 (要想持久性管理,必须在出错时恢复)
会话跟踪 session cookie 隐藏域 地址重写
Spring mvc 处理Ajax 中put请求问题
/**
* 如果直接发送ajax=PUT形式的请求
* 封装的数据
* Employee
* [empId=1014, empName=null, gender=null, email=null, dId=null]
*
* 问题:
* 请求体中有数据;
* 但是Employee对象封装不上;
* update tbl_emp where emp_id = 1014;
*
* 原因:
* Tomcat:
* 1、将请求体中的数据,封装一个map。
* 2、request.getParameter("empName")就会从这个map中取值。
* 3、SpringMVC封装POJO对象的时候。
* 会把POJO中每个属性的值,request.getParamter("email");
* AJAX发送PUT请求引发的血案:
* PUT请求,请求体中的数据,request.getParameter("empName")拿不到
* Tomcat一看是PUT不会封装请求体中的数据为map,只有POST形式的请求才封装请求体为map
* org.apache.catalina.connector.Request--parseParameters() (3111);
*
* protected String parseBodyMethods = "POST";
* if( !getConnector().isParseBodyMethod(getMethod()) ) {
success = true;
return;
}
*
*
* 解决方案;
* 我们要能支持直接发送PUT之类的请求还要封装请求体中的数据
* 1、配置上HttpPutFormContentFilter;
* 2、他的作用;将请求体中的数据解析包装成一个map。
* 3、request被重新包装,request.getParameter()被重写,就会从自己封装的map中取数据
* 员工更新方法
* @param employee
* @return
*/
SSM Maven 下整合笔记
- 新建maven 项目 并在 pom.xml中引入需要的包
- Spring的相关配置applicationContext.xml
- 开启自动扫描组件
<context:component-scan base-package="com.cws">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" /> </context:component-scan>
(2)Spring配置数据库连接池采用c3p0连接池
<context:property-placeholder location="classpath:dbconfig.properties" />
<bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ssm_crud?useUnicode=true&characterEncoding=utf8"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
(3)Mybatis注入连接池 并将mapper 相关的管理绑定
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="dataSource" ref="pooledDataSource"></property>
<!-- 指定mybatis,mapper文件的位置 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
</bean>
(4).配置扫描器,将mybatis接口实现注入ioc容器
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--扫描所有dao接口的实现,加入到ioc容器中 -->
<property name="basePackage" value="com.cws.dao"></property>
</bean>
(5)Spring的事务管理(切入点,事务增强)
<!--切入点设置 -->
<aop:config>
<aop:pointcut expression="execution(* com.cws.service..*(..))"
id="txPointcut" />
<aop:advisor advice-ref="txadvice" pointcut-ref="txPointcut" />
</aop:config>
<!-- 事务增强 *代表所有方法 -->
<tx:advice id="txadvice">
<tx:attributes>
<tx:method name="*" />
<tx:method name="get*" read-only="true" />
</tx:attributes>
</tx:advice>
二, mybatis-config.xml的配置
主要开启驼峰命名 别名处理器等 其他数据库连接在Spring中处理
三,SpringMvc的配置
在web.xml中springmvc的前端控制器,拦截所有请求,放入同意目录下并保证名字为servlet-name-servlet.xml
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
dispatcherServlet-servlet.xml,
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--SpringMVC的配置文件,包含网站跳转逻辑的控制,配置 -->
<context:component-scan base-package="com" use-default-filters="false">
<!--只扫描控制器。 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--配置视图解析器,方便页面返回 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--两个标准配置 -->
<!-- 将springmvc不能处理的请求交给tomcat -->
<mvc:default-servlet-handler/>
<!-- 能支持springmvc更高级的一些功能,JSR303校验,快捷的ajax...映射动态请求 -->
<mvc:annotation-driven/>
Java 的屏幕坐标是以像素为单位,容器的左上角被确定为坐标的起点。
1.final修饰变量,则等同于常量
2.final修饰方法中的参数,称为最终参数。
3.final修饰类,则类不能被继承
4.final修饰方法,则方法不能被重写。
方法重载(overload):
1.必须是同一个类
2方法名(也可以叫函数)一样
3参数类型不一样或参数数量不一样
方法的重写(override)两同两小一大原则:
方法名相同,参数类型相同
子类返回类型小于等于父类方法返回类型,
子类抛出异常小于等于父类方法抛出异常,
子类访问权限大于等于父类方法访问权限
抽象类和接口的区别
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然
eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
5. 抽象类中可以包含静态方法,接口中不能包含静态方法
6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
7. 一个类可以实现多个接口,但只能继承一个抽象类。
ThreadLocal 线程局部变量
1、ThreadLocal的类声明:
public class ThreadLocal<T>
可以看出ThreadLocal并没有继承自Thread,也没有实现Runnable接口。所以AB都不对。
2、ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量。
所以ThreadLocal重要作用并不在于多线程间的数据共享,而是数据的独立,。
由于每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,不会被其他线程访问,变量被彻底封闭在每个访问的线程中。\
规范化解决了数据冗余,更新异常,插入异常,删除异常四个问题