diff --git a/week_06/05/BoundedBlockingQueue.java b/week_06/05/BoundedBlockingQueue.java new file mode 100644 index 0000000000000000000000000000000000000000..485bdf6ce829f8100f00c4f2f6f978ecf31facb8 --- /dev/null +++ b/week_06/05/BoundedBlockingQueue.java @@ -0,0 +1,148 @@ +package com.itliusir.design; + +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +class BoundedBlockingQueue { + + public static void main(String[] args) throws InterruptedException { + /*BoundedBlockingQueue queue = new BoundedBlockingQueue(2); + // 生产者 + new Thread(() -> { + try { + System.out.println("enqueue 1"); + queue.enqueue(1); + + System.out.println("enqueue 0"); + queue.enqueue(0); + + System.out.println("enqueue 2"); + queue.enqueue(2); + + System.out.println("enqueue 3"); + queue.enqueue(3); + + System.out.println("enqueue 4"); + queue.enqueue(4); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }).start(); + + // 消费者 + new Thread(() -> { + try { + System.out.println("first get: " + queue.dequeue()); + System.out.println("second get: " + queue.dequeue()); + System.out.println("third get: " + queue.dequeue()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + }).start();*/ + Method[] declaredMethods = BoundedBlockingQueue.class.getDeclaredMethods(); + for (Method declaredMethod : declaredMethods) { + System.out.println(declaredMethod.getName()); + } + + } + + private final Lock lock = new ReentrantLock(); + + private final AtomicInteger size = new AtomicInteger(); + + private final int capacity; + + Condition notEmpty = lock.newCondition(); + Condition notFull = lock.newCondition(); + + public BoundedBlockingQueue(int c) { + capacity = c; + } + + public void enqueue(int element) throws InterruptedException { + int currSize = -1; + final Lock lock = this.lock; + final AtomicInteger size = this.size; + Node newNode = new Node(element); + lock.lockInterruptibly(); + try { + while (size.get() == capacity) { + notFull.await(); + } + // 维护指针 start + Node f = first; + newNode.next = f; + first = newNode; + if (last == null) { + last = newNode; + } else { + f.prev = newNode; + } + // 维护指针 end + + notEmpty.signal(); + currSize = size.getAndIncrement(); + if (currSize + 1 < capacity) { + notFull.signal(); + } + } finally { + lock.unlock(); + } + + } + + public int dequeue() throws InterruptedException { + int currSize = -1; + final Lock lock = this.lock; + final AtomicInteger size = this.size; + lock.lockInterruptibly(); + try { + while (size.get() == 0) { + notEmpty.await(); + } + + // 维护指针 start + Node l = last; + Node p = l.prev; + int val = l.val; + l.prev = l; + last = p; + if (p == null) { + first = null; + } else { + p.next = null; + } + // 维护指针 end + + currSize = size.getAndDecrement(); + notFull.signal(); + if (currSize > 1) { + notEmpty.signal(); + } + return val; + } finally { + lock.unlock(); + } + } + + public int size() { + return size.get(); + } + + class Node { + int val; + Node next; + Node prev; + + public Node(int val) { + this.val = val; + } + } + + private Node first; + private Node last; +} \ No newline at end of file diff --git "a/week_06/05/Class\346\272\220\347\240\201\345\210\206\346\236\220.md" "b/week_06/05/Class\346\272\220\347\240\201\345\210\206\346\236\220.md" new file mode 100644 index 0000000000000000000000000000000000000000..de525505cd4dc8a37e177076dc9e93f1317dc056 --- /dev/null +++ "b/week_06/05/Class\346\272\220\347\240\201\345\210\206\346\236\220.md" @@ -0,0 +1,92 @@ +# Class类 源码分析 + +## 1. 基本介绍 + +Class 实例表示正在运行的 Java 应用程序中的类(枚举属于类)和接口(注解属于接口)。 + +## 2. 核心方法分析 + +### 2.1 生成实例 + +```java +@CallerSensitive +public T newInstance() + throws InstantiationException, IllegalAccessException +{ + // 安全校验 + if (System.getSecurityManager() != null) { + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); + } + // 检查缓存 + if (cachedConstructor == null) { + // 排除 Class 类 + if (this == Class.class) { + throw new IllegalAccessException( + "Can not call newInstance() on the Class for java.lang.Class" + ); + } + try { + Class[] empty = {}; + // 获取无参构造方法 + final Constructor c = getConstructor0(empty, Member.DECLARED); + // 设置访问权限 + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + c.setAccessible(true); + return null; + } + }); + // 缓存起来 + cachedConstructor = c; + } catch (NoSuchMethodException e) { + throw (InstantiationException) + new InstantiationException(getName()).initCause(e); + } + } + Constructor tmpConstructor = cachedConstructor; + // 获取构造方法的修饰符(public private ...) + int modifiers = tmpConstructor.getModifiers(); + // 判断是否有访问权限 + if (!Reflection.quickCheckMemberAccess(this, modifiers)) { + // 获取调用者的类 + Class caller = Reflection.getCallerClass(); + if (newInstanceCallerCache != caller) { + Reflection.ensureMemberAccess(caller, this, null, modifiers); + newInstanceCallerCache = caller; + } + } + try { + // 使用类的构造方法来生成实例 + return tmpConstructor.newInstance((Object[])null); + } catch (InvocationTargetException e) { + Unsafe.getUnsafe().throwException(e.getTargetException()); + return null; + } +} +``` + +### 2.2 获取类信息 + +获取类的所有方法 + +```java +@CallerSensitive +public Method[] getDeclaredMethods() throws SecurityException { + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + return copyMethods(privateGetDeclaredMethods(false)); +} +// 通过 ReflectionFactory 获取 method[] +private static Method[] copyMethods(Method[] arg) { + Method[] out = new Method[arg.length]; + ReflectionFactory fact = getReflectionFactory(); + for (int i = 0; i < arg.length; i++) { + out[i] = fact.copyMethod(arg[i]); + } + return out; +} +``` + +## 3. 总结 + +Class类主要提供了加载、初始化、生产实例和类信息的获取以及类型转换等 API,方便了我们开发人员的操作。 \ No newline at end of file diff --git a/week_06/05/MyCircularDeque.java b/week_06/05/MyCircularDeque.java new file mode 100644 index 0000000000000000000000000000000000000000..c361ccf47aff5820d61cbbeee4301556171dcb58 --- /dev/null +++ b/week_06/05/MyCircularDeque.java @@ -0,0 +1,110 @@ +package com.itliusir.design; + +class MyCircularDeque { + + public static void main(String[] args) { + MyCircularDeque circularDeque = new MyCircularDeque(3); + System.out.println(circularDeque.insertLast(1)); + System.out.println(circularDeque.insertLast(2)); + System.out.println(circularDeque.insertFront(3)); + System.out.println(circularDeque.insertFront(4)); + System.out.println(circularDeque.getRear()); + System.out.println(circularDeque.isFull()); + System.out.println(circularDeque.deleteLast()); + System.out.println(circularDeque.insertFront(4)); + System.out.println(circularDeque.getFront()); + } + + final int[] queue; + int front, rear; + int capacity; + int count; + + public MyCircularDeque(int k) { + queue = new int[k]; + capacity = k; + front = 0;rear = 0; + count = 0; + } + + /** + * 将一个元素添加到双端队列头部 + * */ + public boolean insertFront(int value) { + if (isFull()) { + return false; + } + queue[front] = value; + front = (front - 1 + capacity) % capacity; + count++; + return true; + } + + /** + * 将一个元素添加到双端队列尾部 + * */ + public boolean insertLast(int value) { + if (isFull()) { + return false; + } + rear = (rear + 1) % capacity; + queue[rear] = value; + count++; + return true; + } + + /** + * 从双端队列头部删除一个元素 + * */ + public boolean deleteFront() { + if (isEmpty()) { + return false; + } + front = (front+1) % capacity; + count--; + return true; + } + + /** + * 从双端队列尾部删除一个元素 + * */ + public boolean deleteLast() { + if (isEmpty()) { + return false; + } + rear = (rear - 1 + capacity) % capacity; + count--; + return true; + } + + /** + * 从双端队列头部获得一个元素 + * */ + public int getFront() { + if (isEmpty()) { + return -1; + } + return queue[(front + 1) % capacity]; + } + + /** + * 获得双端队列的最后一个元素 + * */ + public int getRear() { + if (isEmpty()) { + return -1; + } + return queue[rear]; + } + + /** + * 将一个元素添加到双端队列头部 + * */ + public boolean isEmpty() { + return count == 0; + } + + public boolean isFull() { + return count == capacity; + } +} \ No newline at end of file diff --git a/week_06/05/MyCircularQueue.java b/week_06/05/MyCircularQueue.java new file mode 100644 index 0000000000000000000000000000000000000000..2849a153141040e91bfeebddcf9a9c3ae6249811 --- /dev/null +++ b/week_06/05/MyCircularQueue.java @@ -0,0 +1,85 @@ +package com.itliusir.design; + +/** + * TODO + * + * @author liugang + * @since 2020/1/17 + */ +public class MyCircularQueue { + + public static void main(String[] args) { + MyCircularQueue circularQueue = new MyCircularQueue(3); + System.out.println(circularQueue.enQueue(1)); + System.out.println(circularQueue.enQueue(2)); + System.out.println(circularQueue.enQueue(3)); + System.out.println(circularQueue.enQueue(4)); + System.out.println(circularQueue.Rear()); + System.out.println(circularQueue.isFull()); + System.out.println(circularQueue.deQueue()); + System.out.println(circularQueue.enQueue(4)); + System.out.println(circularQueue.Rear()); + } + + final int[] table; + int front, rear = -1, len = 0; + + public MyCircularQueue(int k) { + table = new int[k]; + } + + /** + * 插入元素 + */ + public boolean enQueue(int value) { + if (!isFull()) { + rear = (rear + 1) % table.length; + table[rear] = value; + len++; + return true; + } else { + return false; + } + } + + /** + * 删除元素 + */ + public boolean deQueue() { + if (!isEmpty()) { + front = (front + 1) % table.length; + len--; + return true; + } else { + return false; + } + } + + /** + * 获取队首元素 + */ + public int Front() { + return isEmpty() ? -1 : table[front]; + } + + /** + * 获取队尾元素 + */ + public int Rear() { + return isEmpty() ? -1 : table[rear]; + } + + /** + * 是否为空 + */ + public boolean isEmpty() { + return len == 0; + } + + /** + * 是否已满 + */ + public boolean isFull() { + return len == table.length; + } +} diff --git a/week_06/05/MyHashMap.java b/week_06/05/MyHashMap.java new file mode 100644 index 0000000000000000000000000000000000000000..5698182892eeda9111e8e50a6d0491d3e288bed8 --- /dev/null +++ b/week_06/05/MyHashMap.java @@ -0,0 +1,88 @@ +package com.itliusir.design; + + +/** + * @author liugang + * @date 2020-01-16 + */ +public class MyHashMap { + + public static void main(String[] args) { + MyHashMap map = new MyHashMap(); + map.put(1, 1); + map.put(2, 2); + System.out.println(map.get(1)); + System.out.println(map.get(2)); + } + + final ListNode[] nodes = new ListNode[10000]; + + public void put(int key, int value) { + int idx = idx(key); + if (nodes[idx] == null) { + nodes[idx] = new ListNode(-1, -1); + } + // 查找可更新的地址元素 + ListNode prev = find(nodes[idx], key); + // 无则新增 + if (prev.next == null) { + prev.next = new ListNode(key, value); + // 有则更新 + } else { + prev.next.value = value; + } + } + + public int get(int key) { + int idx = idx(key); + if (nodes[idx] == null) { + return -1; + } + ListNode prev = find(nodes[idx], key); + return prev.next == null ? -1 : prev.next.value; + } + + public void remove(int key) { + int idx = idx(key); + if (nodes[idx] == null) { + return; + } + ListNode prev = find(nodes[idx], key); + if (prev.next == null) { + return; + } + prev.next = prev.next.next; + } + + + + + ListNode find(ListNode node, int key) { + ListNode curr = node; + ListNode prev = null; + // terminate + // condition 1: curr == null + // condition 2: key == key + while (curr != null && curr.key != key) { + prev = curr; + curr = curr.next; + } + return prev; + } + + int idx(int key) { + return Integer.hashCode(key) % nodes.length; + } + + + static class ListNode { + int key; + int value; + ListNode next; + + ListNode(int key, int value) { + this.key = key; + this.value = value; + } + } +} diff --git a/week_06/05/MyHashSet.java b/week_06/05/MyHashSet.java new file mode 100644 index 0000000000000000000000000000000000000000..e3152a5c78a227f16b133959f896f05f7837188b --- /dev/null +++ b/week_06/05/MyHashSet.java @@ -0,0 +1,84 @@ +package com.itliusir.design; + +/** + * generate a hashSet + * + * @author liugang + * @since 2020/1/17 + */ +public class MyHashSet { + + final ListNode[] table = new ListNode[10000]; + + public static void main(String[] args) { + MyHashSet set = new MyHashSet(); + set.add(7); + set.add(6); + System.out.println(set.contains(5)); + System.out.println(set.contains(7)); + System.out.println(set.contains(6)); + } + + + public void add(int key) { + int idx = idx(key); + if (table[idx] == null) { + table[idx] = new ListNode(-1); + } + ListNode prev = find(table[idx], key); + if (prev.next == null) { + prev.next = new ListNode(key); + } else { + prev.next.value = key; + } + } + + public void remove(int key) { + int idx = idx(key); + if (table[idx] == null) { + return; + } + ListNode prev = find(table[idx], key); + if (prev.next == null) { + return; + } else { + prev.next = prev.next.next; + } + } + + public boolean contains(int key) { + int idx = idx(key); + if (table[idx] == null) { + return false; + } + ListNode prev = find(table[idx], key); + if (prev.next == null) { + return false; + } else { + return true; + } + } + + int idx(int key) { + return Integer.hashCode(key) % table.length; + } + + ListNode find(ListNode node, int key) { + ListNode curr = node, prev = null; + while (curr != null && curr.value != key) { + prev = curr; + curr = curr.next; + } + return prev; + } + + + class ListNode { + int value; + ListNode next; + + public ListNode(int value) { + this.value = value; + } + } +} diff --git a/week_06/05/MyLinkedList.java b/week_06/05/MyLinkedList.java new file mode 100644 index 0000000000000000000000000000000000000000..f28054982e2d1a78422e58605c6594c7a051a55a --- /dev/null +++ b/week_06/05/MyLinkedList.java @@ -0,0 +1,107 @@ +package com.itliusir.design; + +class MyLinkedList { + + public static void main(String[] args) { + MyLinkedList linkedList = new MyLinkedList(); + linkedList.addAtHead(1); + linkedList.addAtTail(3); + linkedList.addAtIndex(1, 2); + System.out.println(linkedList.get(1)); + linkedList.deleteAtIndex(1); + System.out.println(linkedList.get(1)); + } + + public MyLinkedList() { + + } + + /** + * 获取链表中第 index 个节点的值 + * */ + public int get(int index) { + if (index >= size) return -1; + Node currentNode = head; + for (int i = 0; i < index; i++) { + currentNode = currentNode.next; + } + return currentNode.val; + } + + /** + * 添加头节点(头结点之前) + * */ + public void addAtHead(int val) { + Node prev = head; + head = new Node(val); + head.next = prev; + size++; + } + + /** + * 添加尾结点 + * */ + public void addAtTail(int val) { + Node newNode = new Node(val); + size++; + if (head == null) { + head = newNode; + } else { + Node currentNode = head; + while (currentNode.next != null) { + currentNode = currentNode.next; + } + currentNode.next = newNode; + } + } + + /** + * 指定位置添加节点 + * */ + public void addAtIndex(int index, int val) { + if (index > size) return; + if (index == 0) { + addAtHead(val); + } else if (index == size){ + addAtTail(val); + } else { + Node newNode = new Node(val); + size++; + Node currentNode = head; + for (int i = 0; i < index - 1; i++) { + currentNode = currentNode.next; + } + newNode.next = currentNode.next; + currentNode.next = newNode; + } + } + + /** + * 删除指定位置节点 + * */ + public void deleteAtIndex(int index) { + if (index >= size) return; + size--; + if (index == 0) { + head = head.next; + return; + } + Node currentNode = head; + for (int i = 0; i < index - 1; i++) { + currentNode = currentNode.next; + } + currentNode.next = currentNode.next.next; + } + + class Node { + int val; + Node next; + + public Node(int val) { + this.val = val; + } + } + + private Node head; + private int size; +} \ No newline at end of file diff --git a/week_06/05/Mybatis.md b/week_06/05/Mybatis.md new file mode 100644 index 0000000000000000000000000000000000000000..415580005a07f20680dc8a41eec070f22b0c8b1c --- /dev/null +++ b/week_06/05/Mybatis.md @@ -0,0 +1,25 @@ +# Mybatis + +##1. 架构 + +![](http://qiniu.itliusir.com/mybatis01.png) + +## 2. 项目模块 + +| 模块 | 内容 | +| -------------- | :----------------------------------------------------------: | +| **基础支持层** | 数据源、事务管理、缓存、Binding、反射、类型转换、日志、资源加载、解析器 | +| **核心处理层** | 配置解析、参数映射、SQL解析、SQL执行、结果集映射、插件 | +| **接口层** | SqlSession | + +### 2.1 基础支持层 + +Mybatis 的基础支持层主要是自己为了方便封装了一套抽象层,例如反射模块提供了更简洁的API,日志与事务模块方便扩展集成,Binding 模块减轻开发人员负担等。 + +### 2.2 核心处理层 + +核心处理层包括了配置的解析(构建SqlSession),SQL的解析(解析动态sql节点生成可执行sql),SQL的执行(实参绑定、执行SQL),插件的扩展(如拦截SQL) + +### 2.3 接口层 + +接口抽象层,定义了 Mybatis 与上层应用的交互桥梁,根据上层请求调用核心处理层的模块来完成操作 \ No newline at end of file diff --git a/week_06/05/SpringFramework.md b/week_06/05/SpringFramework.md new file mode 100644 index 0000000000000000000000000000000000000000..2413fffd46692801dfaf7a75e5f8961054b7beb1 --- /dev/null +++ b/week_06/05/SpringFramework.md @@ -0,0 +1,17 @@ +# Spring Framework + +##1. 架构 + + + +## 2. 项目模块 + +| 模块 | 内容 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| [Core](https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/core.html#spring-core) | IoC Container, Events, Resources, i18n, Validation, Data Binding, Type Conversion, SpEL, AOP. | +| [Testing](https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/testing.html#testing) | Mock Objects, TestContext Framework, Spring MVC Test, WebTestClient. | +| [Data Access](https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/data-access.html#spring-data-tier) | Transactions, DAO Support, JDBC, O/R Mapping, XML Marshalling. | +| [Web Servlet](https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/web.html#spring-web) | Spring MVC, WebSocket, SockJS, STOMP Messaging. | +| [Web Reactive](https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/web-reactive.html#spring-webflux) | Spring WebFlux, WebClient, WebSocket. | +| [Integration](https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/integration.html#spring-integration) | Remoting, JMS, JCA, JMX, Email, Tasks, Scheduling, Caching. | +| [Languages](https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/languages.html#languages) | Kotlin, Groovy, Dynamic Languages. | \ No newline at end of file