2018-03-11 14:19:50    137    0    0

1. 线程安全
Brian Goetz给出的线程安全定义:当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象时线程安全的。

A. Java语言中的线程安全
a. 不可变
不可变(immutable)的对象一定是线程安全的,无论是对象的方法实现还是方法的调用者,都不需要再采取任何的线程安全保障措施。
b. 绝对线程安全
绝对的线程安全完全满足Brian Goetz给出的线程安全的定义,而Vector这类的线程安全的容器,并不是绝对安全的。

  1. import java.util.Vector;
  2. /**
  3. * Created by sakura on 2018/3/11.
  4. */
  5. public class VectorDemo {
  6. private static Vector<Integer> vector=new Vector<Integer>();
  7. public static void main(String[] args) {
  8. while(true){
  9. for(int i=0;i<10;i++){
  10. vector.add(i);
  11. }
  12. Thread removeThread=new Thread(new Runnable() {
  13. @Override
  14. public void run() {
  15. for(int i=0;i<vector.size();i++){
  16. vector.remove(i);
  17. }
  18. }
  19. });
  20. Thread printThread=new Thread(new Runnable() {
  21. @Override
2018-03-10 18:59:51    359    0    0

计算机大量的时间都花费在磁盘I/O、网络通信或者数据库访问上了。
基于高速缓存的存储交互很好地解决了处理器与内存的速度矛盾,但也引入了缓存一致性(Cache Coherence)的问题。
缓存一致性协议有MSI、MESI(Illinois Protocol)、MOSI、Synapse、Firefly及Dragon Protocol等。
图片标题
内存模型:可以理解为在特定的操作协议下,对特定的内存或高速缓存进行读写访问的抽象过程。

1. Java内存模型
Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽掉各种硬件和操作系统的内存访问差距,以实现让Java程序在各种平台下都能达到一致的内存访问效果。
A. 主内存与工作内存
Java内存模型规定了所有的变量都存储在主内存(Main Memory)中。每个线程还有自己的工作内存,线程的工作内存中保存了被此线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。
图片标题
B. 内存间交互操作
关于主内存与工作内存之间具体的交互协议,即一个变量如何从主内存拷贝到工作内存、如何从工作内存同步回主内存之类的实现细节,Java内存模型中定义了以下8种操作来完成,虚拟机实现时必须保证下面提及的每一种操作都是原子的、不可再分的(double和long类型的变量属于特殊情况)。
lock(锁定):作用于主内存的变量,它把一个变量标识为一条线程独占的状态。
unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
read(读取):作用于主内存内的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用。
load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
use(使用):作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到

2018-03-07 10:04:23    268    0    0

业务基本流程:
新用户注册->校验用户名是否存在
用户名、密码、确认密码、电话、邮箱、密码提示问题、密码提示答案

然后注册成功,进行登录(这里也可以点击忘记密码进行密码找回)

登录成功后,在我的mmall里面可以修改个人信息

首页可以动态的搜索 i关键字搜索,海尔 美的 华为 iPhone
也会有分类的id查询,看到手机分类点进去,可以按价格动态排序
加入购物车 查看购物车
全选 单选 购物车的价格会实时的计算 并且可以增加和减少数量
去结算
新增收货地址 保存收货地址 地址添加成功 可以对其编辑和删除
提交订单 生成订单号 扫码支付二维码
您的订单支付成功!
查看订单 订单信息 商品清单 点击我的订单 分页

后台
登录
订单管理 查看 立即发货 按订单号查询 分页
品类管理 查看子品类 新增品类 修改名称
商品管理 按商品id查询 修改上下架

数据表结构设计:
1. 用户表
主键:id
唯一索引:username

  1. DROP TABLE IF EXISTS `mmall_user`;
  2. CREATE TABLE `mmall_user` (
  3. `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户表id',
  4. `username` varchar(50) NOT NULL COMMENT '用户名',
  5. `password` varchar(50) NOT NULL COMMENT '用户密码,MD5加密',
  6. `email` varchar(50) DEFAULT NULL,
  7. `phone` varchar(20) DEFAULT NULL,
  8. `question` varchar(100) DEFAULT NULL COMMENT '找回密码问题',
  9. `answer` varchar(100) DEFAULT NULL COMMENT '找回密码答案',
  10. `role` int(4) NOT NULL COMMENT '角色0-管理员,1-普通用户',
  11. `create_time` datetime NOT NULL COMMEN
2018-02-27 17:07:37    186    0    0

基础版本,仅仅是spring IOC的基本实现,并未涉及到设计模式,主要包含:
a. Java的反射机制
b. 自定义注解的实现
c. 文件的递归查询

Create New Project
图片标题
Project name设为springioc->Finish

这是最后的项目目录结构:
图片标题


Controller:

  1. package com.earnfish.annotion;
  2. import java.lang.annotation.*;
  3. /**
  4. * 定义controller注解,用于标注控制器类
  5. */
  6. @Target(ElementType.TYPE)
  7. @Retention(RetentionPolicy.RUNTIME)
  8. @Documented
  9. public @interface Controller {
  10. String value() default "";
  11. }

Qualifier:

  1. package com.earnfish.annotion;
  2. import java.lang.annotation.*;
  3. @Target(ElementType.FIELD)
  4. @Retention(RetentionPolicy.RUNTIME)
  5. @Documented
  6. public @interface Qualifier {
  7. String value() default "";
  8. }

RequestMapping:

  1. package com.earnfish.annotion;
  2. import java.lang.annotation.*;
  3. @Target(ElementType.METHOD)
  4. @Retention(RetentionPolicy.RUNTIME)
  5. @Documented
  6. public @interface RequestMapping {
  7. String value() default "";
  8. }

Service:

  1. package com.earnfish.annotion;
  2. import java.lang.annotation.*;
  3. /**
  4. * 定义service注解,用于标注服务类
  5. * */
  6. @Target(ElementType.TYPE)
2018-02-14 08:53:57    491    0    0

第3章 对象的共享
要编写正确的并发程序,关键问题在于:在访问共享的可变状态时需要进行正确的管理。通过同步来避免多个线程在同一时刻访问相同的数据。
synchronized:
1. 用于实现原子性或者确定临界区(Critical Section)
2. 内存可见性(Memory Visibility)
我们不仅希望防止某个线程正在使用对象状态而另一个线程在同时修改此状态,而且希望确保当一个线程修改了对象状态后,其他线程能够看到发生的状态变化。

1. 可见性
当读操作和写操作在不同的线程中执行时,通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情。
可见性:即一个线程修改了某个变量的值,这个新值对其他线程来说是立即可见的。
Sharing Variables without Synchronization:

  1. /**
  2. * Created by sakura on 2018/2/14.
  3. */
  4. public class NoVisibility {
  5. private static boolean ready;
  6. private static int number;
  7. private static class ReaderThread extends Thread {
  8. public void run() {
  9. while (!ready)
  10. Thread.yield();
  11. System.out.println(number);
  12. }
  13. }
  14. public static void main(String[] args) {
  15. new ReaderThread().start();
  16. number = 42;
  17. ready = true;
  18. }
  19. }

在没有同步的情况下,编译器、处理器以及运行时等都可能对操作的执行顺序进行一些意想不到的调整。在缺乏足够同步的多线程程序中,要想对内存操作的执行顺序进行判断,几乎无法得出正确的结论。

A. 失效数据

2018-02-13 13:57:06    484    0    0

第5章 初始化和清理
用构造器确保初始化
创建对象时,如果其类具有构造器,Java就会在用户有能力操作对象之前自动调用相应的构造器,从而保证了初始化的进行。由于构造器的名称必须与类名完全相同,所以每个方法首字母小写的编码风格并不适用于构造器。在Java中,初始化和创建捆绑在一起,两者不能分离。

方法重载
在Java(和C++)里,构造器是强制重载方法名的另一个原因。

区分重载方法
每个重载的方法都必须有一个独一无二的参数类型列表,甚至参数顺序的不同也足以区分两个方法。

以返回值区分重载方法?

  1. void f() {}
  2. int f() { return 1; }
  3. f();

根据方法的返回值来区分重载方法是行不通的。

默认构造器
如果你写的类中没有构造器,则编译器会自动帮你创建一个默认构造器。

  1. class Bird {}
  2. public class DefaultConstructor {
  3. public static void main(String[] args) {
  4. Bird b = new Bird(); // Default!
  5. }
  6. }

但是,如果已经定义了一个构造器(无论是否有参数),编译器就不会帮你自动创建默认构造器。

  1. class Bird2 {
  2. Bird2(int i) {}
  3. Bird2(double d) {}
  4. }
  5. public class NoSynthesis {
  6. public static void main(String[] args) {
  7. //! Bird2 b = new Bird2(); // No default
  8. Bird2 b2 = new Bird2(1);
  9. Bird2 b3 = new Bird2(1.0);
  10. }
  11. }

new Bird2();这样写编译器就会报错:没有找到匹配的构造器。

this关键字

  1. class Banana { void peel(int i) { /* ... */ } }
  2. public class BananaPeel {
  3. public static void main(String
2018-02-11 18:28:02    415    0    0

第1章 网络基础
根据Web浏览器地址栏中指定的URL,Web浏览器从Web服务器端获取文件资源(resource)等信息,从而显示出Web页面。
Web使用一种名为HTTP(HyperText Transfer Protocol,超文本传输协议)的协议作为规范,完成从客户端到服务器端等一系列运作流程。而协议是指规则的约定。可以说,Web是建立在HTTP协议上通信的。
WWW=World Wide Web

TCP/IP协议族
计算机与网络设备要相互通信,双方就必须基于相同的方法。比如,如何探测到通信目标、由哪一边先发起通信、使用哪种语言进行通信、怎样结束通信等规则都需要事先确定。不同的硬件、操作系统之间的通信,所有的这一切都需要一种规则,而我们就把这种规则称为协议(protocol)。

TCP/IP协议族按层次分别分为以下4层:应用层、传输层、网络层和数据链路层。
应用层:
决定了向用户提供应用服务时通信的活动,HTTP也属于应用层。
FTP(File Transfer Protocol,文件传输协议)
DNS(Domain Name System,域名系统)

传输层:
对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。
TCP(Transmission Control Protocol,传输控制协议)
UDP(User Data Protocol,用户数据报协议)

网络层:
用来处理在网络上流动的数据包,数据包是网络传输的最小数据单位。网络层规定了通过怎样的路径(所谓的传输路线)到达对方计算机,并把数据包传送给对方。与对方计算机之间通过多台计算机或网络设备进行传输时,网络层所起的作用就是在众多的选项内选择一条传输路线。

链路层:
用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动、NIC(Network Interface Card,网络适配卡,即网卡),及光纤等物理可见部分(还包括连接器等一切传输媒介)。硬件上的范畴均在链路层的作用范围之内。

TCP/IP通信传输流
图片标题

与HTTP关系密切的协议:IP、TCP和DNS
负责传输的IP协议
按层次分,IP(Internet Proto

2018-02-10 13:58:50    392    0    0

第1章 对象导论
面向对象程序设计(Object-oriented Programming,OOP)
所有编程语言都提供抽象机制,可以认为,所能够解决的问题的复杂性直接取决于抽象的类型和质量。
必须建立起在机器模型(位于解空间内)和实际待解问题的模型(位于问题空间内)之间的关联。
把问题空间中的元素在其解空间中的表示称为对象
纯粹的面向对象语言的5个特性:
1. 一切都是对象
2. 程序是对象的集合,之间通过调用请求发送消息
3. 每个对象都有自己的由其他对象所构成的存储
4. 每个对象都拥有其类型
5. 某一特定类型的所有对象都可以接收同样的消息(多态)
对象具有自己的属性和行为。
在程序执行期间具有不同的状态而其他方面都相似的对象会被分组到对象的类中,这就是关键字class的由来。创建抽象数据类型(类)是面向对象程序设计的基本概念之一,抽象数据类型的运行方式与内置类型几乎完全一致。因为类描述了具有相同特性(数据元素)和行为(功能)的对象集合,所以一个类实际上就是一个数据类型,程序员通过定义类来适应问题,而不再被迫只能使用现有的用来表示机器中的存储单元的数据类型。

每个对象都提供服务
高内聚,低耦合
组合 has a
继承 is a

多态
编译器不可能产生传统意义上的函数调用,一个非面向对象编程的编译器产生的函数调用会引起所谓的前期绑定,这意味着编译器会产生对一个具体函数名字的调用,而运行时把这个调用解析到要被执行的代码的绝对地址。面向对象程序设计语言使用了后期绑定的概念,当向对象发送消息时,被调用的代码直到运行时才能确定。编译器确保被调用方法的存在,并对调用参数和返回值执行类型检查(无法提供此类保证的语言被称为是弱类型的),但是不知道要被执行的确切代码。

程序的可扩展性:

  1. void doSomething(Shape shape) {
  2. shape.erase();
  3. // ...
  4. shape.draw();
  5. }
  6. Circle circle = new Circle();
  7. Triangle triangle = new Triangle();
  8. Line line= new Line();
  9. doSom
2018-01-28 16:02:34    174    0    0

基本概念和背景
一些计算机组成的知识点:
1. 程序必须装入内存后,才能(以进程为单位)被CPU解释、执行
2. CPU能够直接访问的,只有主存、寄存器
3. 访问寄存器需要1个CPU时钟周期,很快
4. 访问主存需要许多时钟周期,或者,需要若干机器周期
5. Cache位于主存、寄存器之间

连续区内存分配
基地址(base)寄存器和界限(limit)寄存器共同划定逻辑地址空间。

逻辑地址空间vs物理地址空间
区别于物理地址空间的各种逻辑地址空间,是OS得以管理内存的必要条件。
逻辑地址:CPU产生的地址,也称为虚地址。
逻辑地址:非物理的各种地址标记包括符号名,包括编译、汇编、连接、装入操作产生的地址。
物理地址:内存单元接收到的地址。也就是说,浮现在地址总线的地址,以二进制形式表达。

存储管理单元(MMU)
CPU内部的硬件装置,其功能是把虚拟地址(逻辑地址)转换成物理地址。
一种简单的MMU策略是,在用户进程把逻辑地址送往地址总线前,MMU把重定位寄存器(relocation register)的值,加到这个逻辑地址。
用户进程只能处理逻辑地址,无法获取真正的物理地址。

交换(Swapping)
进程映像暂时传输到后备存储空间保存(换出,swap out),需要(执行)时再装入内存(换入,swap in)。

存储管理基本思想
y=f(x)
x为逻辑地址,y为物理地址
存储管理算法的评估和比较
1. 硬件支持 Hardware Support
2. 性能 Performance
3. 碎片 Fragmentation
4. 重定位 Relocation
5. 交换 Swapping
6. 内存共享 Memory sharing
7. 内存保护 Memory protection

非连续区内存分配
1. 页式内存管理
注意进程并不要求逻辑地址必须是连续的。
把物理空间等分成长度一致的数据块,称作页帧(frames),操作系统对空闲页帧进行统一管理。
把逻辑空间等分成长度一致的数据块,称作页(pages),并且与页帧长度相等。
通常,页长(也就是页帧长度)是2的幂次,

green    2018-01-04 21:18:46    189    0    0

1. final、finally和finalize的区别
final:
被final修饰的类不能被继承;
被final修饰的方法不能被重写;
被final修饰的变量不能被更改。

finally:
是异常处理的一部分,用于释放资源。一般来说,finally里面的代码一定会执行,除非在finally之前调用System.exit()方法终止JVM的运行。

finalize:
是Object类的一个方法,用于垃圾回收。
引用深入理解JVM一书中的一段话:
即使在可达性分析算法中不可达的对象,也并非是“非死不可”的,这时它们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经理两次标记过程:如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机把这两种情况都视为“没有必要执行”。如果这个对象被判定为有必要执行finalize()方法,那么这个对象会被放置在一个叫F-Queue的队列之中,并在稍后由一个由虚拟机自动建立的、低优先级的Finalizer线程去执行它。这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束(防止发生死循环)。finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC会对F-Queue中的对象进行第二次标记,如果对象在finalize()方法中成功拯救自己——只要重新和引用链上的任何一个对象建立关联即可,那么在第二次标记时它会被移除出“即将回收”的集合,如果对象这个时间点还没有逃脱,那基本上它就真的被回收了。

2. 如果catch里面有return语句,那么finally里面的代码还会执行吗?执行顺序?
finally语句是在try的return语句执行之后,return返回之前执行。

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. /**
  4. * Created by sakura on 2018/1/4.
  5. */
  6. public class