├── .gitignore ├── LICENSE.txt ├── README.md ├── codemarks ├── pom.xml └── src │ └── main │ └── java │ └── rest │ └── api │ └── result │ ├── Result.java │ ├── ResultCode.java │ └── ResultGenerator.java ├── concurrent ├── pom.xml └── src │ └── main │ └── java │ ├── cas │ ├── AtomicSequence.java │ └── Sequence.java │ ├── juc │ ├── CopyOnWriteArrayTest.java │ ├── CountDownLatchTest.java │ ├── CyclicBarrierTest.java │ ├── ExecutorTest.java │ ├── ForkJoinTest.java │ ├── SemaphoreTest.java │ ├── ThreadPoolExecutorTest.java │ ├── TimeUnitTest.java │ ├── aqs │ │ ├── MutexLock.java │ │ └── MutexLockTest.java │ ├── automic │ │ ├── AtomicIntegerTest.java │ │ └── AtomicityProblemTest.java │ └── lock │ │ ├── ConditionTest.java │ │ ├── ReentrantLockTest.java │ │ └── ReentrantReadWriteLockTest.java │ ├── pcmodel │ ├── ProducerConsumerModelBlockQueueImpl.java │ └── ProducerConsumerModelWaitNotifyImpl.java │ ├── synchronizeds │ ├── SynchronizedCodeBlockTest.java │ ├── SynchronizedMethodTest.java │ ├── SynchronizedStaticMethodTest.java │ └── SynchronizedTest.java │ ├── thread │ ├── DeadlockTest.java │ ├── HowToCreateThread.java │ ├── InterruptTest.java │ ├── JoinTest.java │ ├── NotifyTest.java │ ├── TimedJoinTest.java │ ├── WaitTest.java │ └── YieldTest.java │ ├── unsafe │ ├── CustomAtomicInteger.java │ ├── PrivateConstructTestClass.java │ ├── TestClass.java │ ├── UnsafeLock.java │ ├── UnsafeLockTest.java │ └── UnsafeTest.java │ └── volatiles │ ├── Singleton.java │ └── VolatileTest.java ├── container └── pom.xml ├── data-structure-algorithm ├── pom.xml └── src │ └── main │ └── java │ ├── arithmetic │ ├── BinarySearch.java │ ├── BubbleSort.java │ ├── HeapSort.java │ ├── InsertSort.java │ ├── QuickSort.java │ ├── SelectSort.java │ └── ShellSort.java │ └── data │ └── structure │ ├── queue │ ├── Queue.java │ ├── QueueLinkedImpl.java │ └── Tester.java │ └── stack │ ├── Stack.java │ ├── StackArrayImpl.java │ ├── StackLinkedImpl.java │ └── Tester.java ├── design-pattern ├── pom.xml └── src │ └── main │ └── java │ ├── behavioral │ └── package-info.java │ ├── creational │ ├── AbstractFactoryPattern.java │ ├── BuilderPattern.java │ ├── FactoryMethodPattern.java │ ├── PrototypePattern.java │ ├── SimpleFactoryPattern.java │ ├── SingletonPattern.java │ ├── StaticFactoryMethodPattern.java │ └── package-info.java │ └── structural │ ├── AdapterPattern.java │ ├── BridgePattern.java │ ├── DecoratorPattern.java │ ├── FacadePattern.java │ ├── ProxyPattern.java │ └── package-info.java ├── io ├── pom.xml └── src │ └── main │ └── java │ └── ReadFile.java ├── jvm ├── pom.xml └── src │ └── main │ └── java │ ├── Test.java │ └── classloader │ └── CustomClassLoader.java ├── pom.xml ├── shared-resources ├── README.md ├── Spring Boot 1.4.1 中文文档.epub ├── Spring Boot 最佳实践.pdf ├── Spring Boot 笔记.docx ├── Spring Data JPA 1.4.3 中文文档.pdf ├── Spring Security 4.1 中文文档.pdf ├── github-images │ ├── druid-spring-boot-starter-ide-hint.jpg │ ├── issue-31 │ │ ├── step1.png │ │ └── step2.png │ ├── project-example-youku.png │ └── project-struct.png ├── java.util.concurrent.xmind ├── 阿里巴巴Java开发手册V1.2.0.pdf └── 阿里巴巴Java开发手册V1.3.0.pdf └── socket ├── pom.xml └── src └── main └── java ├── echo ├── Client.java └── EchoServer.java ├── netty ├── HelloClient.java └── NettyTest.java └── rpc ├── RpcTest.java └── SimpleRpcFramework.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 lihengming 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 温故而知新 2 | > “温故而知新”有三解。一为“温故才知新”:温习已学的知识,并且由其中获得新的领悟;二为“温故及知新”:一方面要温习典章故事,另一方面又努力撷取新的知识。三为,温故,知新。随着自己阅历的丰富和理解能力的提高,回头再看以前看过的知识,总能从中体会到更多的东西。 3 | 4 | ## 项目目录 5 | - [数据结构 & 算法](https://github.com/lihengming/java-codes/tree/master/data-structure-algorithm) 6 | - [常见排序算法](https://github.com/lihengming/java-codes/tree/master/data-structure-algorithm/src/main/java/arithmetic) 7 | - [基础数据结构](https://github.com/lihengming/java-codes/tree/master/data-structure-algorithm/src/main/java/data/structure) 8 | - [JVM](https://github.com/lihengming/java-codes/tree/master/jvm) 9 | - [自定义类加载器](https://github.com/lihengming/java-codes/blob/master/jvm/src/main/java/classloader/CustomClassLoader.java) 10 | - [并发](https://github.com/lihengming/java-codes/tree/master/concurrent) 11 | - [Synchronized ](https://github.com/lihengming/java-codes/tree/master/concurrent/src/main/java/synchronizeds) 12 | - [Volatile](https://github.com/lihengming/java-codes/tree/master/concurrent/src/main/java/volatiles) 13 | - [线程的创建 & 协作](https://github.com/lihengming/java-codes/tree/master/concurrent/src/main/java/thread) 14 | - [Java 并发工具包](https://github.com/lihengming/java-codes/tree/master/concurrent/src/main/java/juc) 15 | - [CAS](https://github.com/lihengming/java-codes/tree/master/concurrent/src/main/java/cas) 16 | - [Unsafe](https://github.com/lihengming/java-codes/tree/master/concurrent/src/main/java/unsafe) 17 | - [生产者 - 消费者模型](https://github.com/lihengming/java-codes/tree/master/concurrent/src/main/java/pcmodel) 18 | - [网络](https://github.com/lihengming/java-codes/tree/master/socket) 19 | - [一个类实现RPC框架](https://github.com/lihengming/java-codes/tree/master/socket/src/main/java/rpc) 20 | - [设计模式](https://github.com/lihengming/java-codes/tree/master/design-pattern) 21 | - [创建型模式(Creational)](https://github.com/lihengming/java-codes/tree/master/design-pattern/src/main/java/creational) 22 | - [简单工厂模式(Simple Factory)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/creational/SimpleFactoryPattern.java) 23 | - [工厂方法模式(Factory Method)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/creational/FactoryMethodPattern.java) 24 | - [抽象工厂模式(Abstract Factory)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/creational/AbstractFactoryPattern.java) 25 | - [静态工厂方法模式(Static Factory Method)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/creational/StaticFactoryMethodPattern.java) 26 | - [创建者模式(Builder)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/creational/BuilderPattern.java) 27 | - [原型模式(Prototype)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/creational/PrototypePattern.java) 28 | - [单例模式(Singleton)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/creational/SingletonPattern.java) 29 | - [结构型模式(Structural)](https://github.com/lihengming/java-codes/tree/master/design-pattern/src/main/java/structural) 30 | - [外观(门面)模式(Facade)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/structural/FacadePattern.java) 31 | - [适配器模式(Adapter)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/structural/AdapterPattern.java) 32 | - [代理模式(Proxy)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/structural/ProxyPattern.java) 33 | - [装饰模式(Decorator)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/structural/DecoratorPattern.java) 34 | - [桥接模式(Bridge)](https://github.com/lihengming/java-codes/blob/master/design-pattern/src/main/java/structural/BridgePattern.java) 35 | - 组合模式(Composite) 36 | - 享元模式(Flyweight) 37 | - [行为型模式(Behavioral)](https://github.com/lihengming/java-codes/tree/master/design-pattern/src/main/java/behavioral) 38 | - 模板方法模式(Template Method) 39 | - 观察者模式(Observer) 40 | - 状态模式(State) 41 | - 策略模式(Strategy) 42 | - 职责链模式(Chain of Responsibility) 43 | - 命令模式(Command) 44 | - 访问者模式(Visitor) 45 | - 调停者模式(Mediator) 46 | - 备忘录模式(Memento) 47 | - 迭代器模式(Iterator) 48 | - 解释器模式(Interpreter) 49 | - [资源分享](https://github.com/lihengming/java-codes/tree/master/shared-resources) 50 | - [代码收藏夹](https://github.com/lihengming/java-codes/tree/master/codemarks) 51 | 52 | ## 相关文章 53 | 54 | - 浅析JVM系列 55 | - [x] [浅析JVM(一)Class文件&类加载机制](http://www.jianshu.com/p/5f3278916b38) 56 | - [x] [浅析JVM(二)运行时数据区](http://www.jianshu.com/p/460aeab77b7f) 57 | - [x] [浅析JVM(三)GC](http://www.jianshu.com/p/bf41e3425e64) 58 | 59 | - 浅析Java并发编程系列 60 | - [x] [浅析Java并发编程(一)基础概念&理论](http://www.jianshu.com/p/f4cdcc90290a) 61 | - [x] [浅析Java并发编程(二)synchronized & volatile](http://www.jianshu.com/p/7713f95b1a67) 62 | - [x] [浅析Java并发编程(三)线程的状态&协作](http://www.jianshu.com/p/7cc1c01f7655) 63 | - [x] [浅析Java并发编程(四)java.util.concurrent](http://www.jianshu.com/p/47ff843bcfe7) 64 | - [x] [浅析Java并发编程(五)CAS&Unsafe&AQS的“秘密”](http://www.jianshu.com/p/54cc20a87502) 65 | 66 | ## 关于 67 | - 本项目的两大作用 68 | 1. 温故基础、收藏可复用代码、分享资源。 69 | 2. 存放[我的技术博客](http://www.jianshu.com/u/335a31051c58)上相关文章包含的代码。 70 | - 本项目基于```Java 8```,构建工具为```Maven```,部分测试代码使用```Junit```运行,内容持续更新。 71 | -------------------------------------------------------------------------------- /codemarks/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | java-codes 7 | com.github.lihengming 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | codemarks 13 | 14 | 15 | -------------------------------------------------------------------------------- /codemarks/src/main/java/rest/api/result/Result.java: -------------------------------------------------------------------------------- 1 | package rest.api.result; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/13. 5 | *

6 | * 统一API JSON 响应结果 7 | */ 8 | public class Result { 9 | 10 | private int code; 11 | private String message; 12 | private Object data; 13 | 14 | public Result setCode(ResultCode resultCode) { 15 | this.code = resultCode.code; 16 | return this; 17 | } 18 | 19 | public int getCode() { 20 | return code; 21 | } 22 | 23 | public Result setCode(int code) { 24 | this.code = code; 25 | return this; 26 | } 27 | 28 | public String getMessage() { 29 | return message; 30 | } 31 | 32 | public Result setMessage(String message) { 33 | this.message = message; 34 | return this; 35 | } 36 | 37 | public Object getData() { 38 | return data; 39 | } 40 | 41 | public Result setData(Object data) { 42 | this.data = data; 43 | return this; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "Result{" + 49 | "code=" + code + 50 | ", message='" + message + '\'' + 51 | ", data=" + data + 52 | '}'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /codemarks/src/main/java/rest/api/result/ResultCode.java: -------------------------------------------------------------------------------- 1 | package rest.api.result; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/13. 5 | *

6 | * 响应码枚举 7 | */ 8 | public enum ResultCode { 9 | SUCCESS(200),//成功 10 | FAIL(400),//失败 11 | Unauthorized(401),//未认证(签名错误) 12 | NOT_FOUND(404),//接口不存在 13 | INTERNAL_SERVER_ERROR(500);//服务器内部错误 14 | 15 | public int code; 16 | 17 | ResultCode(int code) { 18 | this.code = code; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /codemarks/src/main/java/rest/api/result/ResultGenerator.java: -------------------------------------------------------------------------------- 1 | package rest.api.result; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/13. 5 | *

6 | * 响应结果生成工具 7 | */ 8 | public class ResultGenerator { 9 | private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS"; 10 | 11 | public static Result genSuccessResult() { 12 | return new Result() 13 | .setCode(ResultCode.SUCCESS) 14 | .setMessage(DEFAULT_SUCCESS_MESSAGE); 15 | } 16 | 17 | public static Result genSuccessResult(Object data) { 18 | return new Result() 19 | .setCode(ResultCode.SUCCESS) 20 | .setMessage(DEFAULT_SUCCESS_MESSAGE) 21 | .setData(data); 22 | } 23 | 24 | public static Result genFailResult(String message) { 25 | return new Result() 26 | .setCode(ResultCode.FAIL) 27 | .setMessage(message); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /concurrent/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | java-codes 7 | com.github.lihengming 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | concurrent 13 | 14 | 15 | -------------------------------------------------------------------------------- /concurrent/src/main/java/cas/AtomicSequence.java: -------------------------------------------------------------------------------- 1 | package cas; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/20. 7 | */ 8 | public class AtomicSequence { 9 | private AtomicInteger value = new AtomicInteger(); 10 | 11 | public int next() { 12 | while (true) { 13 | int expect = value.get(); 14 | int next = expect + 1; 15 | if (value.compareAndSet(expect, next)) { 16 | return next; 17 | } 18 | } 19 | 20 | } 21 | 22 | public int next2() { 23 | return value.incrementAndGet(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /concurrent/src/main/java/cas/Sequence.java: -------------------------------------------------------------------------------- 1 | package cas; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/20. 5 | */ 6 | public class Sequence { 7 | private int value; 8 | public synchronized int next() { 9 | return value++; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/CopyOnWriteArrayTest.java: -------------------------------------------------------------------------------- 1 | package juc; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.CopyOnWriteArrayList; 5 | 6 | /** 7 | * Created by 李恒名 on 2017/6/18. 8 | */ 9 | public class CopyOnWriteArrayTest { 10 | 11 | public static void main(String[] args) { 12 | //List list = new ArrayList<>();//java.lang.ArrayIndexOutOfBoundsException 13 | final List list = new CopyOnWriteArrayList<>(); 14 | int maxThreads = 10; 15 | 16 | for (int i = 0; i < maxThreads; i++) { 17 | new Thread(() -> { 18 | for (int j = 0; j < 100000; j++) { 19 | list.add(new Object()); 20 | } 21 | }).start(); 22 | } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/CountDownLatchTest.java: -------------------------------------------------------------------------------- 1 | package juc; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/18. 7 | */ 8 | public class CountDownLatchTest { 9 | static CountDownLatch latch = new CountDownLatch(3);//创建计数器并设置初始值为3 10 | 11 | static void work() { 12 | System.out.println(Thread.currentThread().getName() + " Work End"); 13 | latch.countDown();//计数器值-1 14 | } 15 | 16 | public static void main(String[] args) throws InterruptedException { 17 | new Thread(() -> work()).start(); 18 | new Thread(() -> work()).start(); 19 | new Thread(() -> work()).start(); 20 | 21 | latch.await();//当前线程(主线程)等待计数器值为0,才会执行 22 | System.out.println("Main Thread Work End"); 23 | 24 | /** 25 | 输出: 26 | Thread-0 Work End 27 | Thread-1 Work End 28 | Thread-2 Work End 29 | Main Thread Work End 30 | */ 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/CyclicBarrierTest.java: -------------------------------------------------------------------------------- 1 | package juc; 2 | 3 | import java.util.concurrent.BrokenBarrierException; 4 | import java.util.concurrent.CyclicBarrier; 5 | 6 | /** 7 | * Created by 李恒名 on 2017/6/18. 8 | */ 9 | public class CyclicBarrierTest { 10 | //定义一个barrier并设置parties,当线程数达到parties后,barrier失效,线程可以继续运行,在未达到parties值之前,线程将持续等待。 11 | static CyclicBarrier barrier = new CyclicBarrier(3,()-> System.out.println("栅栏:“这么多猪,我恐怕扛不住了”")); 12 | 13 | static void go() { 14 | System.out.println("小猪[" + Thread.currentThread().getName() + "] 在栅栏边等待其他小猪"); 15 | try { 16 | barrier.await();//等待数+1 17 | } catch (InterruptedException e) { 18 | e.printStackTrace(); 19 | } catch (BrokenBarrierException e) { 20 | e.printStackTrace(); 21 | } 22 | System.out.println("猪到齐了,小猪[" + Thread.currentThread().getName() + "] 与其他小猪一起冲破栅栏"); 23 | } 24 | 25 | public static void main(String[] args) { 26 | 27 | new Thread(() -> go()).start(); 28 | new Thread(() -> go()).start(); 29 | new Thread(() -> go()).start(); 30 | 31 | /** 32 | 输出: 33 | 小猪[Thread-0] 在栅栏边等待其他小猪 34 | 小猪[Thread-1] 在栅栏边等待其他小猪 35 | 小猪[Thread-2] 在栅栏边等待其他小猪 36 | 栅栏:“这么多猪,我恐怕扛不住了” 37 | 猪到齐了,小猪[Thread-2] 与其他小猪一起冲破栅栏 38 | 猪到齐了,小猪[Thread-0] 与其他小猪一起冲破栅栏 39 | 猪到齐了,小猪[Thread-1] 与其他小猪一起冲破栅栏 40 | */ 41 | } 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/ExecutorTest.java: -------------------------------------------------------------------------------- 1 | package juc; 2 | 3 | import java.util.concurrent.*; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/18. 7 | */ 8 | public class ExecutorTest { 9 | public static void main(String[] args) { 10 | //创建固定线程数的线程池 11 | ExecutorService es = Executors.newFixedThreadPool(2); 12 | //执行传统Runnable任务 13 | es.execute(new RunnableTask()); 14 | //执行Callable任务并获得任务结果Future 15 | Future future = es.submit(new CallableTask()); 16 | try { 17 | System.out.println("Calculate Completed Sum:" + future.get()); 18 | } catch (InterruptedException | ExecutionException e) { 19 | e.printStackTrace(); 20 | } 21 | //关键线程池 22 | es.shutdown(); 23 | /** 24 | 输出: 25 | pool-1-thread-1 Started By Runnable 26 | pool-1-thread-2 Started By Callable 27 | Calculate Completed Sum:2 28 | */ 29 | } 30 | } 31 | class CallableTask implements Callable { 32 | @Override 33 | public Object call() throws Exception { 34 | System.out.println(Thread.currentThread().getName() + " Started By Callable"); 35 | //求和 36 | return 1 + 1; 37 | } 38 | } 39 | class RunnableTask implements Runnable { 40 | @Override 41 | public void run() { 42 | System.out.println(Thread.currentThread().getName() + " Started By Runnable"); 43 | 44 | } 45 | } 46 | 47 | 48 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/ForkJoinTest.java: -------------------------------------------------------------------------------- 1 | package juc; 2 | 3 | import java.util.concurrent.ForkJoinPool; 4 | import java.util.concurrent.Future; 5 | import java.util.concurrent.RecursiveTask; 6 | 7 | /** 8 | * Created by 李恒名 on 2017/6/19. 9 | */ 10 | public class ForkJoinTest { 11 | 12 | static class Sum extends RecursiveTask { 13 | private static final int THRESHOLD = 10;//可直接求解的临界值 14 | private final long from; 15 | private final long to; 16 | 17 | Sum(long from, long to) { 18 | this.from = from; 19 | this.to = to; 20 | } 21 | 22 | @Override 23 | protected Long compute() { 24 | long sum = 0; 25 | if ((to - from) < THRESHOLD) {//达到直接求解的临界点,直接进行计算 26 | for (long i = from; i <= to; i++) { 27 | sum = sum + i; 28 | } 29 | } else {//递归分解计算 30 | long mid = (from + to) >>> 1;//取中间值 31 | //以中间值为界将计算任务分解执行 32 | Sum left = new Sum(from, mid); 33 | left.fork(); 34 | Sum right = new Sum(mid + 1, to); 35 | right.fork(); 36 | //合并计算结果 37 | sum = left.join() + right.join(); 38 | } 39 | return sum; 40 | } 41 | } 42 | 43 | public static void main(String[] args) throws Exception { 44 | ForkJoinPool forkJoinPool = new ForkJoinPool(); 45 | Future result = forkJoinPool.submit(new Sum(1, 10000)); 46 | System.out.println("Sum:" + result.get());//Sum:50005000 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/SemaphoreTest.java: -------------------------------------------------------------------------------- 1 | package juc; 2 | 3 | import java.util.concurrent.Semaphore; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | /** 7 | * Created by 李恒名 on 2017/6/18. 8 | */ 9 | public class SemaphoreTest { 10 | public static void main(String[] args) { 11 | WC wc = new WC(); 12 | new Thread(() -> wc.use()).start(); 13 | new Thread(() -> wc.use()).start(); 14 | new Thread(() -> wc.use()).start(); 15 | 16 | new Thread(() -> wc.use()).start(); 17 | new Thread(() -> wc.use()).start(); 18 | /** 19 | 输出: 20 | Thread-1 正在使用卫生间 21 | Thread-2 正在使用卫生间 22 | Thread-0 正在使用卫生间 23 | Thread-0 使用完毕 24 | Thread-2 使用完毕 25 | Thread-1 使用完毕 26 | Thread-3 正在使用卫生间 27 | Thread-4 正在使用卫生间 28 | Thread-4 使用完毕 29 | Thread-3 使用完毕 30 | */ 31 | } 32 | } 33 | 34 | class WC { 35 | private Semaphore semaphore = new Semaphore(3);//最大线程许可量 36 | 37 | public void use() { 38 | try { 39 | //获得许可 40 | semaphore.acquire(); 41 | System.out.println(Thread.currentThread().getName() +" 正在使用卫生间"); 42 | TimeUnit.SECONDS.sleep(3); 43 | System.out.println(Thread.currentThread().getName() +" 使用完毕"); 44 | } catch (InterruptedException e) { 45 | e.printStackTrace(); 46 | } finally{ 47 | //释放许可 48 | semaphore.release(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/ThreadPoolExecutorTest.java: -------------------------------------------------------------------------------- 1 | package juc; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | import java.util.concurrent.LinkedBlockingQueue; 5 | import java.util.concurrent.ThreadPoolExecutor; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by 李恒名 on 2017/6/18. 10 | */ 11 | public class ThreadPoolExecutorTest { 12 | public static void main(String[] args) { 13 | BlockingQueue workQueue = new LinkedBlockingQueue<>(5);//工作队列容量5 14 | int corePoolSize = 1;//核心线程数1 15 | int maximumPoolSize = 2;//最大线程数2 16 | ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 1, TimeUnit.MILLISECONDS, workQueue); 17 | 18 | executor.execute(new TestTask());//执行任务,创建一个核心线程 19 | 20 | executor.execute(new TestTask());//核心线程忙,放入队列,队列内任务数+1 21 | executor.execute(new TestTask());//核心线程忙,放入队列,队列内任务数+1 22 | executor.execute(new TestTask());//核心线程忙,放入队列,队列内任务数+1 23 | executor.execute(new TestTask());//核心线程忙,放入队列,队列内任务数+1 24 | executor.execute(new TestTask());//核心线程忙,放入队列,队列内任务数+1 25 | System.out.println("WorkQueue Size:" + workQueue.size());//WorkQueue Size:5,队列满 26 | 27 | executor.execute(new TestTask());//核心线程忙,队列也满了,继续新的线程执行任务 28 | System.out.println("PoolSize Size:" + executor.getPoolSize());//PoolSize Size:2,达到最大线程数 29 | 30 | executor.execute(new TestTask());//继续执行任务,则抛出异常,拒绝服务 31 | 32 | executor.shutdown(); 33 | 34 | /** 35 | 输出: 36 | WorkQueue Size:5 37 | PoolSize Size:2 38 | Exception in thread "main" java.util.concurrent.RejectedExecutionException: 39 | Task juc.TestTask@45ee12a7 rejected from java.util.concurrent.ThreadPoolExecutor@330bedb4 40 | [Running, pool size = 2, active threads = 1, queued tasks = 5, completed tasks = 0] 41 | */ 42 | } 43 | 44 | } 45 | 46 | class TestTask implements Runnable{ 47 | 48 | @Override 49 | public void run() { 50 | try { 51 | TimeUnit.DAYS.sleep(1); 52 | } catch (InterruptedException e) { 53 | e.printStackTrace(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/TimeUnitTest.java: -------------------------------------------------------------------------------- 1 | package juc; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/17. 7 | */ 8 | public class TimeUnitTest { 9 | 10 | public static void main(String[] args) throws InterruptedException { 11 | //睡眠13分钟 12 | TimeUnit.MINUTES.sleep(13); 13 | //Thread.sleep(780000);//这样写你知道是多久吗? 14 | //Thread.sleep(13*60*1000);//这样写会稍微好些 15 | 16 | //睡眠1小时 17 | TimeUnit.HOURS.sleep(1); 18 | //Thread.sleep(3600000); 19 | 20 | TimeUnitTest test = new TimeUnitTest(); 21 | 22 | Thread thread = new Thread(() -> test.work()); 23 | 24 | //10秒内Join 25 | TimeUnit.SECONDS.timedJoin(thread,10); 26 | //thread.join(10000); 27 | 28 | 29 | } 30 | 31 | public synchronized void work() { 32 | System.out.println("Begin Work"); 33 | try { 34 | //等待30秒后,自动唤醒继续执行 35 | TimeUnit.SECONDS.timedWait(this, 30); 36 | //wait(30000); 37 | } catch (InterruptedException e) { 38 | e.printStackTrace(); 39 | } 40 | System.out.println("Work End"); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/aqs/MutexLock.java: -------------------------------------------------------------------------------- 1 | package juc.aqs; 2 | 3 | import java.io.IOException; 4 | import java.io.ObjectInputStream; 5 | import java.util.concurrent.TimeUnit; 6 | import java.util.concurrent.locks.AbstractQueuedSynchronizer; 7 | import java.util.concurrent.locks.Condition; 8 | import java.util.concurrent.locks.Lock; 9 | 10 | /** 11 | * Created by 李恒名 on 2017/6/22. 12 | */ 13 | public class MutexLock implements Lock, java.io.Serializable { 14 | 15 | // 继承ASQ实现同步组件 16 | private static class Sync extends AbstractQueuedSynchronizer { 17 | @Override 18 | //通过状态判断锁是否已被其他线程获取 19 | protected boolean isHeldExclusively() { 20 | 21 | return getState() == 1; 22 | } 23 | @Override 24 | //尝试获取锁 25 | public boolean tryAcquire(int acquires) { 26 | //尝试获取锁,当 state 为 0 时获得锁,并将state + 1,由CAS保证操作的原子性 27 | if (compareAndSetState(0, 1)) { 28 | setExclusiveOwnerThread(Thread.currentThread()); 29 | return true; 30 | } 31 | return false; 32 | } 33 | @Override 34 | //尝试释放锁 35 | protected boolean tryRelease(int releases) { 36 | if (getState() == 0) throw new IllegalMonitorStateException(); 37 | setExclusiveOwnerThread(null); 38 | //直接将state 设置为 0,以便等待队列中的线程去获得锁 39 | setState(0); 40 | return true; 41 | } 42 | 43 | // Provides a Condition 44 | Condition newCondition() { return new ConditionObject(); } 45 | 46 | // Deserializes properly 47 | private void readObject(ObjectInputStream s) 48 | throws IOException, ClassNotFoundException { 49 | s.defaultReadObject(); 50 | setState(0); // reset to unlocked state 51 | } 52 | } 53 | 54 | private final Sync sync = new Sync(); 55 | //使用AQS提供的模板方法 56 | public void lock() { sync.acquire(1); } 57 | public boolean tryLock() { return sync.tryAcquire(1); } 58 | public void unlock() { sync.release(1); } 59 | public Condition newCondition() { return sync.newCondition(); } 60 | public boolean isLocked() { return sync.isHeldExclusively(); } 61 | public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } 62 | public void lockInterruptibly() throws InterruptedException { 63 | sync.acquireInterruptibly(1); 64 | } 65 | public boolean tryLock(long timeout, TimeUnit unit) 66 | throws InterruptedException { 67 | return sync.tryAcquireNanos(1, unit.toNanos(timeout)); 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/aqs/MutexLockTest.java: -------------------------------------------------------------------------------- 1 | package juc.aqs; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/22. 5 | */ 6 | public class MutexLockTest { 7 | public static void main(String[] args) { 8 | TestTask test = new TestTask(); 9 | new Thread(() -> test.method1()).start(); 10 | new Thread(() -> test.method2()).start(); 11 | 12 | /** 13 | 输出: 14 | method1() execute! 15 | method2() execute! 16 | 17 | 不加锁的话: 18 | method2() execute! 19 | method1() execute! 20 | */ 21 | } 22 | 23 | static class TestTask { 24 | private MutexLock lock = new MutexLock(); 25 | 26 | public void method1() { 27 | lock.lock(); 28 | try { 29 | //模拟方法需要执行100毫秒 30 | Thread.sleep(100); 31 | System.out.println("method1() execute!"); 32 | } catch (InterruptedException e) { 33 | e.printStackTrace(); 34 | } finally { 35 | lock.unlock(); 36 | } 37 | } 38 | 39 | public void method2() { 40 | lock.lock(); 41 | try { 42 | System.out.println("method2() execute!"); 43 | } finally { 44 | lock.unlock(); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/automic/AtomicIntegerTest.java: -------------------------------------------------------------------------------- 1 | package juc.automic; 2 | 3 | import org.junit.Assert; 4 | 5 | import java.util.concurrent.atomic.AtomicInteger; 6 | 7 | /** 8 | * Created by 李恒名 on 2017/6/18. 9 | */ 10 | public class AtomicIntegerTest { 11 | 12 | public static AtomicInteger sharedValue = new AtomicInteger(); 13 | 14 | //每次将sharedValue的值增加10 15 | public static void increment() { 16 | for (int i = 0; i < 10; i++) { 17 | sharedValue.incrementAndGet(); 18 | } 19 | } 20 | 21 | public static void main(String[] args) throws InterruptedException { 22 | 23 | int maxThreads = 10000; 24 | for (int i = 0; i < maxThreads; i++) { 25 | Thread thread = new Thread(() -> increment()); 26 | thread.start(); 27 | } 28 | 29 | Thread.sleep(3000);//等待所有子线程执行完成 30 | Assert.assertEquals(sharedValue.get(), 10000 * 10); 31 | //Assert Pass 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/automic/AtomicityProblemTest.java: -------------------------------------------------------------------------------- 1 | package juc.automic; 2 | 3 | import org.junit.Assert; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/17. 7 | */ 8 | public class AtomicityProblemTest { 9 | 10 | public static int sharedValue; 11 | 12 | //每次将sharedValue的值增加10 13 | public static void increment() { 14 | for (int i = 0; i < 10; i++) { 15 | sharedValue++; 16 | } 17 | } 18 | 19 | public static void main(String[] args) throws InterruptedException { 20 | 21 | int maxThreads = 10000; 22 | for (int i = 0; i < maxThreads; i++) { 23 | Thread thread = new Thread(() -> increment()); 24 | thread.start(); 25 | } 26 | 27 | Thread.sleep(3000);//等待所有子线程执行完成 28 | Assert.assertEquals(sharedValue, 10000 * 10); 29 | //Exception in thread "main" java.lang.AssertionError: expected:<99980> but was:<100000> 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/lock/ConditionTest.java: -------------------------------------------------------------------------------- 1 | package juc.lock; 2 | 3 | import java.util.concurrent.locks.Condition; 4 | import java.util.concurrent.locks.Lock; 5 | import java.util.concurrent.locks.ReentrantLock; 6 | 7 | /** 8 | * Created by 李恒名 on 2017/6/18. 9 | */ 10 | public class ConditionTest { 11 | private final Lock lock = new ReentrantLock(); 12 | private final Condition condition = lock.newCondition(); 13 | 14 | 15 | public void work() { 16 | lock.lock(); 17 | try { 18 | try { 19 | System.out.println("Begin Work"); 20 | condition.await(); 21 | System.out.println("Begin End"); 22 | } catch (InterruptedException e) { 23 | e.printStackTrace(); 24 | } 25 | } finally { 26 | lock.unlock(); 27 | } 28 | } 29 | 30 | public void continueWork() { 31 | lock.lock(); 32 | try { 33 | condition.signalAll(); 34 | } finally { 35 | lock.unlock(); 36 | } 37 | } 38 | 39 | public static void main(String[] args) throws InterruptedException { 40 | ConditionTest test = new ConditionTest(); 41 | new Thread(() -> test.work()).start(); 42 | 43 | //等待3000毫秒后唤醒,继续工作。 44 | Thread.sleep(3000); 45 | test.continueWork(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/lock/ReentrantLockTest.java: -------------------------------------------------------------------------------- 1 | package juc.lock; 2 | 3 | import java.util.concurrent.locks.Lock; 4 | import java.util.concurrent.locks.ReentrantLock; 5 | 6 | /** 7 | * Created by 李恒名 on 2017/6/17. 8 | */ 9 | public class ReentrantLockTest { 10 | 11 | private final Lock lock = new ReentrantLock(); 12 | private String content = "Old"; 13 | 14 | public void write() { 15 | lock.lock(); 16 | //由于ReentrantLock是可重入锁,所以可以重复的加锁。 17 | //lock.lock(); 18 | //lock.lock(); 19 | System.out.println(Thread.currentThread() +" LOCK"); 20 | try { 21 | try { 22 | //模拟方法需要执行100毫秒 23 | Thread.sleep(100); 24 | } catch (InterruptedException e) { 25 | e.printStackTrace(); 26 | } 27 | content = "New"; 28 | System.out.println(Thread.currentThread() +" Write content to: " + content); 29 | } finally { 30 | System.out.println(Thread.currentThread() +" UNLOCK"); 31 | lock.unlock(); 32 | //进行多少次加锁操作,也需要对应多少次解锁操作。 33 | //lock.unlock(); 34 | //lock.unlock(); 35 | } 36 | } 37 | 38 | public void read() { 39 | lock.lock(); 40 | System.out.println(Thread.currentThread() +" LOCK"); 41 | try { 42 | try { 43 | //模拟方法需要执行100毫秒 44 | Thread.sleep(100); 45 | } catch (InterruptedException e) { 46 | e.printStackTrace(); 47 | } 48 | System.out.println(Thread.currentThread() +" Read content is: " + content); 49 | } finally { 50 | System.out.println(Thread.currentThread() +" UNLOCK"); 51 | lock.unlock(); 52 | } 53 | } 54 | 55 | 56 | public static void main(String[] args) { 57 | final ReentrantLockTest test = new ReentrantLockTest(); 58 | // 使用Java 8 lambda 简化代码 59 | new Thread(() -> test.write()).start(); 60 | new Thread(() -> test.read()).start(); 61 | new Thread(() -> test.read()).start(); 62 | 63 | /** 64 | 不使用锁的输出: 65 | Thread[Thread-1,5,main] Read content is: Old 66 | Thread[Thread-2,5,main] Read content is: Old 67 | Thread[Thread-0,5,main] Write content to: New 68 | 69 | 使用锁后: 70 | Thread[Thread-0,5,main] LOCK 71 | Thread[Thread-0,5,main] Write content to: New 72 | Thread[Thread-0,5,main] UNLOCK 73 | Thread[Thread-1,5,main] LOCK 74 | Thread[Thread-1,5,main] Read content is: New 75 | Thread[Thread-1,5,main] UNLOCK 76 | Thread[Thread-2,5,main] LOCK 77 | Thread[Thread-2,5,main] Read content is: New 78 | Thread[Thread-2,5,main] UNLOCK 79 | **/ 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /concurrent/src/main/java/juc/lock/ReentrantReadWriteLockTest.java: -------------------------------------------------------------------------------- 1 | package juc.lock; 2 | 3 | import java.util.concurrent.locks.ReadWriteLock; 4 | import java.util.concurrent.locks.ReentrantReadWriteLock; 5 | 6 | /** 7 | * Created by 李恒名 on 2017/6/17. 8 | */ 9 | public class ReentrantReadWriteLockTest { 10 | 11 | private final ReadWriteLock lock = new ReentrantReadWriteLock(); 12 | private String content = "Old"; 13 | 14 | public void write() { 15 | lock.writeLock().lock(); 16 | System.out.println(Thread.currentThread() +" LOCK"); 17 | try { 18 | try { 19 | //模拟方法需要执行100毫秒 20 | Thread.sleep(100); 21 | } catch (InterruptedException e) { 22 | e.printStackTrace(); 23 | } 24 | content = "New"; 25 | System.out.println(Thread.currentThread() +" Write content to: " + content); 26 | } finally { 27 | System.out.println(Thread.currentThread() +" UNLOCK"); 28 | lock.writeLock().unlock(); 29 | } 30 | } 31 | 32 | public void read() { 33 | lock.readLock().lock(); 34 | System.out.println(Thread.currentThread() +" LOCK"); 35 | try { 36 | try { 37 | //模拟方法需要执行100毫秒 38 | Thread.sleep(100); 39 | } catch (InterruptedException e) { 40 | e.printStackTrace(); 41 | } 42 | System.out.println(Thread.currentThread() +" Read content is: " + content); 43 | } finally { 44 | System.out.println(Thread.currentThread() +" UNLOCK"); 45 | lock.readLock().unlock(); 46 | } 47 | } 48 | 49 | 50 | public static void main(String[] args) { 51 | final ReentrantReadWriteLockTest test = new ReentrantReadWriteLockTest(); 52 | // 使用Java 8 lambda 简化代码 53 | new Thread(() -> test.write()).start(); 54 | new Thread(() -> test.read()).start(); 55 | new Thread(() -> test.read()).start(); 56 | 57 | /** 58 | 输出: 59 | Thread[Thread-0,5,main] LOCK 60 | Thread[Thread-0,5,main] Write content to: New 61 | Thread[Thread-0,5,main] UNLOCK 62 | Thread[Thread-1,5,main] LOCK 63 | Thread[Thread-2,5,main] LOCK 64 | Thread[Thread-1,5,main] Read content is: New 65 | Thread[Thread-2,5,main] Read content is: New 66 | Thread[Thread-1,5,main] UNLOCK 67 | Thread[Thread-2,5,main] UNLOCK 68 | 可以看到两个线程在读的时候可以同时获得锁 69 | **/ 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /concurrent/src/main/java/pcmodel/ProducerConsumerModelBlockQueueImpl.java: -------------------------------------------------------------------------------- 1 | package pcmodel; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | 8 | /** 9 | * Created by 李恒名 on 2017/6/19. 10 | *

11 | * 生产者-消费者模型的阻塞队列实现 12 | */ 13 | public class ProducerConsumerModelBlockQueueImpl { 14 | public static void main(String[] args) { 15 | final int maxSize = 10;//产品最大库存量 16 | BlockingQueue buffer = new LinkedBlockingQueue(maxSize); 17 | ExecutorService es = Executors.newFixedThreadPool(5); 18 | //两个生产者 19 | es.execute(new Producer(buffer)); 20 | es.execute(new Producer(buffer)); 21 | //三个消费者 22 | es.execute(new Consumer(buffer)); 23 | es.execute(new Consumer(buffer)); 24 | es.execute(new Consumer(buffer)); 25 | 26 | es.shutdown(); 27 | 28 | /** 29 | 输出: 30 | ... 31 | 生产者[pool-1-thread-1]生产了一个产品:MAC 32 | 消费者[pool-1-thread-3]消费了一个产品:MAC 33 | 消费者[pool-1-thread-4]消费了一个产品:MAC 34 | 消费者[pool-1-thread-4]消费了一个产品:MAC 35 | 消费者[pool-1-thread-4]消费了一个产品:MAC 36 | 生产者[pool-1-thread-2]生产了一个产品:MAC 37 | 生产者[pool-1-thread-2]生产了一个产品:MAC 38 | 生产者[pool-1-thread-2]生产了一个产品:MAC 39 | ... 40 | */ 41 | } 42 | 43 | //产品 44 | static class Product { 45 | 46 | private String name; 47 | 48 | public Product(String name) { 49 | this.name = name; 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return name; 55 | } 56 | } 57 | //生产者 58 | static class Producer implements Runnable { 59 | 60 | private BlockingQueue buffer; 61 | 62 | public Producer(BlockingQueue buffer) { 63 | this.buffer = buffer; 64 | } 65 | 66 | public void run() { 67 | while (true) { 68 | Product product = new Product("MAC"); 69 | try { 70 | buffer.put(product); 71 | System.out.println("生产者[" + Thread.currentThread().getName() + "]生产了一个产品:" + product); 72 | } catch (InterruptedException e) { 73 | e.printStackTrace(); 74 | } 75 | } 76 | } 77 | } 78 | //消费者 79 | static class Consumer implements Runnable { 80 | 81 | private BlockingQueue buffer; 82 | 83 | public Consumer(BlockingQueue buffer) { 84 | this.buffer = buffer; 85 | } 86 | 87 | public void run() { 88 | while (true) { 89 | try { 90 | System.out.println("消费者[" + Thread.currentThread().getName() + "]消费了一个产品:" + buffer.take()); 91 | } catch (InterruptedException e) { 92 | e.printStackTrace(); 93 | } 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /concurrent/src/main/java/pcmodel/ProducerConsumerModelWaitNotifyImpl.java: -------------------------------------------------------------------------------- 1 | package pcmodel; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | /** 9 | * Created by 李恒名 on 2017/6/19. 10 | * 11 | * 生产者-消费者模型的 Object.wait()、notify()实现 12 | */ 13 | public class ProducerConsumerModelWaitNotifyImpl { 14 | public static void main(String[] args) { 15 | List buffer = new LinkedList(); 16 | ExecutorService es = Executors.newFixedThreadPool(5); 17 | //两个生产者 18 | es.execute(new Producer(buffer)); 19 | es.execute(new Producer(buffer)); 20 | //三个消费者 21 | Consumer consumer = new Consumer(buffer); 22 | es.execute(new Consumer(buffer)); 23 | es.execute(new Consumer(buffer)); 24 | es.execute(new Consumer(buffer)); 25 | 26 | es.shutdown(); 27 | /** 28 | 输出: 29 | ... 30 | 生产者[pool-1-thread-2]生产了一个产品:iPhone 手机 31 | 生产者[pool-1-thread-2]生产了一个产品:iPhone 手机 32 | 消费者[pool-1-thread-5]消费了一个产品:iPhone 手机 33 | 消费者[pool-1-thread-5]消费了一个产品:iPhone 手机 34 | 消费者[pool-1-thread-5]消费了一个产品:iPhone 手机 35 | 消费者[pool-1-thread-5]消费了一个产品:iPhone 手机 36 | 消费者[pool-1-thread-5]消费了一个产品:iPhone 手机 37 | 生产者[pool-1-thread-1]生产了一个产品:iPhone 手机 38 | 消费者[pool-1-thread-4]消费了一个产品:iPhone 手机 39 | 生产者[pool-1-thread-2]生产了一个产品:iPhone 手机 40 | ... 41 | */ 42 | } 43 | 44 | //产品 45 | static class Product { 46 | 47 | private String name; 48 | 49 | public Product(String name) { 50 | this.name = name; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return name; 56 | } 57 | } 58 | 59 | //生产者 60 | static class Producer implements Runnable { 61 | 62 | private final int maxSize = 10;//产品最大库存量 63 | 64 | private List buffer; 65 | 66 | public Producer(List buffer) { 67 | this.buffer = buffer; 68 | } 69 | 70 | public void run() { 71 | while (true) { 72 | synchronized (buffer) { 73 | while (buffer.size() >= maxSize) { 74 | try { 75 | buffer.wait();//将当前线程放入等锁(buffer对象的锁)池,并释放锁。 76 | } catch (InterruptedException e) { 77 | e.printStackTrace(); 78 | } 79 | } 80 | //模拟生产需要500毫秒 81 | try { 82 | Thread.sleep(500); 83 | } catch (InterruptedException e) { 84 | e.printStackTrace(); 85 | } 86 | Product product = new Product("iPhone 手机"); 87 | buffer.add(product); 88 | System.out.println("生产者[" + Thread.currentThread().getName() + "]生产了一个产品:" + product); 89 | buffer.notifyAll();//生产完毕通知等待池内的其他线程(生产者或消费者都有可能) 90 | } 91 | } 92 | } 93 | } 94 | //消费者 95 | static class Consumer implements Runnable { 96 | 97 | private List buffer; 98 | 99 | public Consumer(List buffer) { 100 | this.buffer = buffer; 101 | } 102 | 103 | public void run() { 104 | while (true) { 105 | synchronized (buffer) { 106 | while (buffer.isEmpty()) { 107 | try { 108 | buffer.wait(); 109 | } catch (InterruptedException e) { 110 | e.printStackTrace(); 111 | } 112 | } 113 | System.out.println("消费者[" + Thread.currentThread().getName() + "]消费了一个产品:" + buffer.remove(0)); 114 | buffer.notifyAll();//消费完毕通知等待池内的其他线程(生产者或消费者都有可能) 115 | } 116 | } 117 | } 118 | 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /concurrent/src/main/java/synchronizeds/SynchronizedCodeBlockTest.java: -------------------------------------------------------------------------------- 1 | package synchronizeds; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/14. 5 | *

6 | * 同步代码块 7 | */ 8 | public class SynchronizedCodeBlockTest { 9 | private final Object lock = new Object(); 10 | 11 | public void method1() { 12 | //需获得Class对象的锁方可执行 13 | //synchronized (this.getClass()) 14 | //需获得lock对象的锁方可执行 15 | //synchronized (lock) 16 | //需获得当前对象的锁方可执行 17 | synchronized (this) { 18 | try { 19 | //模拟方法需要执行100毫秒 20 | Thread.sleep(100); 21 | } catch (InterruptedException e) { 22 | e.printStackTrace(); 23 | } 24 | System.out.println("method1() execute!"); 25 | } 26 | } 27 | 28 | public void method2() { 29 | //需获得Class对象的锁方可执行 30 | //synchronized (this.getClass()) 31 | //需获得lock对象的锁方可执行 32 | //synchronized (lock) 33 | //需获得当前对象的锁方可执行 34 | synchronized (this) { 35 | System.out.println("method2() execute!"); 36 | } 37 | } 38 | 39 | public static void main(String[] args) { 40 | final SynchronizedCodeBlockTest test = new SynchronizedCodeBlockTest(); 41 | // 使用Java 8 lambda 简化代码 42 | new Thread(() -> test.method1()).start(); 43 | new Thread(() -> test.method2()).start(); 44 | /** 45 | 输出: 46 | method1() execute! 47 | method2() execute! 48 | 49 | */ 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /concurrent/src/main/java/synchronizeds/SynchronizedMethodTest.java: -------------------------------------------------------------------------------- 1 | package synchronizeds; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/14. 5 | *

6 | * 同步成员方法 7 | */ 8 | public class SynchronizedMethodTest { 9 | 10 | public /*synchronized*/ void method1() { 11 | try { 12 | //模拟方法需要执行100毫秒 13 | Thread.sleep(100); 14 | } catch (InterruptedException e) { 15 | e.printStackTrace(); 16 | } 17 | System.out.println("method1() execute!"); 18 | 19 | } 20 | 21 | public /*synchronized*/ void method2() { 22 | System.out.println("method2() execute!"); 23 | } 24 | 25 | public static void main(String[] args) { 26 | final SynchronizedMethodTest test = new SynchronizedMethodTest(); 27 | // 使用Java 8 lambda 简化代码 28 | new Thread(() -> test.method1()).start(); 29 | new Thread(() -> test.method2()).start(); 30 | 31 | /** 32 | 输出: 33 | method2() execute! 34 | method1() execute! 35 | 36 | 使用synchronized修饰方法后: 37 | method1() execute! 38 | method2() execute! 39 | **/ 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /concurrent/src/main/java/synchronizeds/SynchronizedStaticMethodTest.java: -------------------------------------------------------------------------------- 1 | package synchronizeds; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/14. 5 | * 6 | * 同步静态方法 7 | */ 8 | public class SynchronizedStaticMethodTest { 9 | 10 | public /*synchronized*/ static void method1() { 11 | try { 12 | //模拟方法需要执行100毫秒 13 | Thread.sleep(100); 14 | } catch (InterruptedException e) { 15 | e.printStackTrace(); 16 | } 17 | System.out.println("method1() execute!"); 18 | 19 | } 20 | 21 | public /*synchronized*/ static void method2() { 22 | System.out.println("method2() execute!"); 23 | } 24 | 25 | public static void main(String[] args) { 26 | final SynchronizedStaticMethodTest test1 = new SynchronizedStaticMethodTest(); 27 | final SynchronizedStaticMethodTest test2 = new SynchronizedStaticMethodTest(); 28 | // 使用Java 8 lambda 简化代码 29 | new Thread(() -> test1.method1()).start(); 30 | new Thread(() -> test2.method2()).start(); 31 | 32 | new Thread(() -> SynchronizedStaticMethodTest.method1()).start(); 33 | new Thread(() -> SynchronizedStaticMethodTest.method2()).start(); 34 | 35 | /** 36 | 输出: 37 | method2() execute! 38 | method2() execute! 39 | method1() execute! 40 | method1() execute! 41 | 42 | 使用synchronized修饰方法后: 43 | method1() execute! 44 | method2() execute! 45 | method1() execute! 46 | method2() execute! 47 | **/ 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /concurrent/src/main/java/synchronizeds/SynchronizedTest.java: -------------------------------------------------------------------------------- 1 | package synchronizeds; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/14. 5 | */ 6 | public class SynchronizedTest { 7 | 8 | public synchronized void method1(){ 9 | System.out.println("Hello World!"); 10 | } 11 | 12 | public void method2(){ 13 | synchronized (this){ 14 | System.out.println("Hello World!"); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /concurrent/src/main/java/thread/DeadlockTest.java: -------------------------------------------------------------------------------- 1 | package thread; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/8/29. 7 | * 8 | * 死锁测试,线程1获得A锁(monitor)之后尝试获得B锁,线程2获得B锁后尝试获得A锁,线程1和线程2即产生死锁。 9 | */ 10 | public class DeadlockTest { 11 | public static void main(String[] args) { 12 | Object lockA = new Object(); 13 | Object lockB = new Object(); 14 | new Thread(() -> { 15 | //线程1获得A锁 16 | synchronized (lockA){ 17 | System.out.println("Thread 1 get lock A ."); 18 | //增加死锁发生几率 19 | try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {} 20 | //尝试获得B锁 21 | System.out.println("Thread 1 try get lock B, waiting..."); 22 | synchronized (lockB){ 23 | //永远无法获得B锁,所以不会打印出来 24 | System.out.println("Thread 1 get lock B ."); 25 | } 26 | 27 | } 28 | }, "Thread 1").start(); 29 | new Thread(() -> { 30 | //线程2获得B锁 31 | synchronized (lockB){ 32 | System.out.println("Thread 2 get lock B ."); 33 | //增加死锁发生几率 34 | try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {} 35 | //尝试获得A锁 36 | System.out.println("Thread 2 try get lock A, waiting..."); 37 | synchronized (lockA){ 38 | //永远无法获得A锁,所以不会打印出来 39 | System.out.println("Thread 2 get lock A ."); 40 | } 41 | 42 | } 43 | }, "Thread 2").start(); 44 | 45 | /** 46 | > jstack [pid] 47 | 48 | "Thread 2": 49 | waiting to lock monitor 0x0000000002cc7338 (object 0x000000076b7b31d8, a java.lang.Object), 50 | which is held by "Thread 1" 51 | "Thread 1": 52 | waiting to lock monitor 0x0000000002cc9bc8 (object 0x000000076b7b31e8, a java.lang.Object), 53 | which is held by "Thread 2" 54 | 55 | */ 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /concurrent/src/main/java/thread/HowToCreateThread.java: -------------------------------------------------------------------------------- 1 | package thread; 2 | 3 | import java.util.concurrent.*; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/8. 7 | */ 8 | public class HowToCreateThread { 9 | 10 | public static void main(String[] args) { 11 | method1(); 12 | method2(); 13 | method3(); 14 | } 15 | 16 | public static void method1() { 17 | //继承java.lang.Thread 18 | class Task extends Thread { 19 | 20 | @Override 21 | public void run() { 22 | System.out.println(Thread.currentThread().getName() + " Started"); 23 | } 24 | } 25 | 26 | new Task().start(); 27 | } 28 | 29 | public static void method2() { 30 | //实现 java.lang.Runnable 31 | class Task implements Runnable { 32 | 33 | @Override 34 | public void run() { 35 | System.out.println(Thread.currentThread().getName() + " Started"); 36 | } 37 | } 38 | 39 | new Thread(new Task()).start(); 40 | } 41 | 42 | public static void method3() { 43 | //实现 java.util.concurrent.Callable 44 | class Task implements Callable { 45 | 46 | @Override 47 | public Object call() throws Exception { 48 | System.out.println(Thread.currentThread().getName() + " Started"); 49 | //求和 50 | return 1 + 1; 51 | } 52 | } 53 | 54 | ExecutorService es = Executors.newFixedThreadPool(1); 55 | Future future = es.submit(new Task()); 56 | try { 57 | System.out.println("Calculate Completed Sum:" + future.get()); 58 | } catch (InterruptedException | ExecutionException e) { 59 | e.printStackTrace(); 60 | } 61 | 62 | es.shutdown(); 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /concurrent/src/main/java/thread/InterruptTest.java: -------------------------------------------------------------------------------- 1 | package thread; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/16. 5 | */ 6 | public class InterruptTest { 7 | 8 | public static void main(String[] args) throws InterruptedException { 9 | 10 | Thread thread = new Thread(() -> { 11 | //模拟正在工作 12 | System.out.println(Thread.currentThread().getName()+" Working"); 13 | }); 14 | 15 | thread.start(); 16 | //中断该线程 17 | thread.interrupt(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /concurrent/src/main/java/thread/JoinTest.java: -------------------------------------------------------------------------------- 1 | package thread; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/16. 5 | */ 6 | public class JoinTest { 7 | 8 | public static void main(String[] args) throws InterruptedException { 9 | Thread thread1 = new Thread(() -> System.out.println(Thread.currentThread().getName() + " Work End")); 10 | thread1.start(); 11 | thread1.join();//合并到主线程,主线程将等待该子线程执行完毕才会执行 12 | 13 | Thread thread2 = new Thread(() -> System.out.println(Thread.currentThread().getName() + " Work End")); 14 | thread2.start(); 15 | thread1.join();//合并到主线程,主线程将等待该子线程执行完毕才会执行 16 | 17 | System.out.println("Main Thread Work End"); 18 | 19 | /** 20 | 输出: 21 | Thread-0 Work End 22 | Thread-1 Work End 23 | Main Thread Work End 24 | 25 | 不使用join(): 26 | Main Thread Work End 27 | Thread-0 Work End 28 | Thread-1 Work End 29 | */ 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /concurrent/src/main/java/thread/NotifyTest.java: -------------------------------------------------------------------------------- 1 | package thread; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/16. 5 | */ 6 | public class NotifyTest { 7 | 8 | public synchronized void work() { 9 | System.out.println("Begin Work"); 10 | try { 11 | //等待唤醒 12 | wait(); 13 | } catch (InterruptedException e) { 14 | e.printStackTrace(); 15 | } 16 | System.out.println("Work End"); 17 | } 18 | 19 | public synchronized void continueWork() { 20 | notifyAll(); 21 | } 22 | 23 | public static void main(String[] args) throws InterruptedException { 24 | NotifyTest test = new NotifyTest(); 25 | new Thread(() -> test.work()).start(); 26 | 27 | //等待3000毫秒后唤醒,继续工作。 28 | Thread.sleep(3000); 29 | test.continueWork(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /concurrent/src/main/java/thread/TimedJoinTest.java: -------------------------------------------------------------------------------- 1 | package thread; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/16. 5 | */ 6 | public class TimedJoinTest { 7 | 8 | public static void main(String[] args) throws InterruptedException { 9 | Thread thread = new Thread(() -> { 10 | try { 11 | //模拟子线程需要执行500毫秒 12 | Thread.sleep(500); 13 | } catch (InterruptedException e) { 14 | e.printStackTrace(); 15 | } 16 | System.out.println(Thread.currentThread().getName() + " Work End"); 17 | }); 18 | thread.start(); 19 | thread.join(100);//合并到主线程,主线程将等待该子线程执行完毕才会执行,只等待100毫秒,过时不在等。 20 | 21 | System.out.println("Main Thread Work End"); 22 | 23 | /** 24 | 输出: 25 | Main Thread Work End 26 | Thread-0 Work End 27 | 28 | 删除Thread.sleep(500);或者降到100以内: 29 | Thread-0 Work End 30 | Main Thread Work End 31 | */ 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /concurrent/src/main/java/thread/WaitTest.java: -------------------------------------------------------------------------------- 1 | package thread; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/16. 5 | */ 6 | public class WaitTest { 7 | 8 | public synchronized void work() { 9 | System.out.println("Begin Work"); 10 | try { 11 | //等待1000毫秒后,自动唤醒继续执行 12 | wait(1000); 13 | } catch (InterruptedException e) { 14 | e.printStackTrace(); 15 | } 16 | System.out.println("Work End"); 17 | } 18 | 19 | 20 | public static void main(String[] args) { 21 | WaitTest test = new WaitTest(); 22 | 23 | new Thread(() -> test.work()).start(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /concurrent/src/main/java/thread/YieldTest.java: -------------------------------------------------------------------------------- 1 | package thread; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/16. 5 | */ 6 | public class YieldTest { 7 | 8 | public void work(){ 9 | for (int i = 0; i < 3; i++) { 10 | System.out.println(Thread.currentThread().getName() + " Working"); 11 | Thread.yield(); 12 | } 13 | } 14 | 15 | 16 | public static void main(String[] args) { 17 | YieldTest test = new YieldTest(); 18 | new Thread(() -> test.work()).start(); 19 | new Thread(() -> test.work()).start(); 20 | 21 | /** 22 | 输出: 23 | Thread-0 Working 24 | Thread-1 Working 25 | Thread-0 Working 26 | Thread-1 Working 27 | Thread-0 Working 28 | Thread-1 Working 29 | **/ 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /concurrent/src/main/java/unsafe/CustomAtomicInteger.java: -------------------------------------------------------------------------------- 1 | package unsafe; 2 | 3 | import org.junit.Assert; 4 | import sun.misc.Unsafe; 5 | 6 | import java.lang.reflect.Constructor; 7 | import java.util.concurrent.CountDownLatch; 8 | 9 | /** 10 | * Created by 李恒名 on 2017/6/20. 11 | */ 12 | public class CustomAtomicInteger { 13 | private volatile int value; 14 | private Unsafe unsafe; 15 | private long offset; 16 | 17 | public CustomAtomicInteger() { 18 | try { 19 | //获得Unsafe的构造器 20 | Constructor constructor = Unsafe.class.getDeclaredConstructor(); 21 | //突破私有访问权限 22 | constructor.setAccessible(true); 23 | //创建示例 24 | this.unsafe = constructor.newInstance(); 25 | //获得value变量的内存偏移量即内存地址 26 | offset = unsafe.objectFieldOffset(CustomAtomicInteger.class.getDeclaredField("value")); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | 32 | public int incrementAndGet() { 33 | while (true) { 34 | int expected = value; 35 | int next = expected + 1; 36 | if (unsafe.compareAndSwapInt(this, offset, expected, next)) { 37 | return next; 38 | } 39 | } 40 | } 41 | 42 | public static void main(String[] args) throws InterruptedException { 43 | CustomAtomicInteger atomicInteger = new CustomAtomicInteger(); 44 | int maxThread = 100000; 45 | CountDownLatch latch = new CountDownLatch(maxThread); 46 | for (int i = 0; i < maxThread; i++) { 47 | new Thread(() -> { 48 | System.out.println(atomicInteger.incrementAndGet()); 49 | latch.countDown(); 50 | }).start(); 51 | } 52 | latch.await();//等待所有线程执行完毕 53 | Assert.assertEquals(atomicInteger.incrementAndGet(), maxThread + 1); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /concurrent/src/main/java/unsafe/PrivateConstructTestClass.java: -------------------------------------------------------------------------------- 1 | package unsafe; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/15. 5 | */ 6 | public class PrivateConstructTestClass { 7 | 8 | private int value;// 没有初始化 9 | 10 | public void printValue() { 11 | System.out.println(this.value); 12 | } 13 | 14 | private PrivateConstructTestClass() { 15 | this.value = 1;// 初始化 16 | new Error("don't support reflect."); 17 | } 18 | 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /concurrent/src/main/java/unsafe/TestClass.java: -------------------------------------------------------------------------------- 1 | package unsafe; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/21. 5 | */ 6 | public class TestClass { 7 | private int value;// 没有初始化 8 | 9 | //私有化构造器 10 | private TestClass() { 11 | this.value = 1;// 初始化 12 | //throw new AssertionError("don't support reflect."); 13 | } 14 | 15 | public void printValue() { 16 | System.out.println(this.value); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /concurrent/src/main/java/unsafe/UnsafeLock.java: -------------------------------------------------------------------------------- 1 | package unsafe; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Constructor; 6 | 7 | /** 8 | * Created by 李恒名 on 2017/6/21. 9 | */ 10 | public class UnsafeLock { 11 | private Unsafe unsafe; 12 | 13 | public UnsafeLock() { 14 | try { 15 | //获得Unsafe的构造器 16 | Constructor constructor = Unsafe.class.getDeclaredConstructor(); 17 | //突破私有访问权限 18 | constructor.setAccessible(true); 19 | //创建示例 20 | this.unsafe = constructor.newInstance(); 21 | } catch (Exception e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | 26 | public void lock(Object obj) { 27 | unsafe.monitorEnter(obj); 28 | } 29 | 30 | public void unlock(Object obj) { 31 | unsafe.monitorExit(obj); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /concurrent/src/main/java/unsafe/UnsafeLockTest.java: -------------------------------------------------------------------------------- 1 | package unsafe; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/21. 5 | */ 6 | public class UnsafeLockTest { 7 | 8 | public static void main(String[] args) { 9 | TestTask test = new TestTask(); 10 | new Thread(() -> test.method1()).start(); 11 | new Thread(() -> test.method2()).start(); 12 | 13 | /** 14 | 输出: 15 | method1() execute! 16 | method2() execute! 17 | 18 | 不加锁保持同步: 19 | method2() execute! 20 | method1() execute! 21 | */ 22 | } 23 | 24 | static class TestTask { 25 | private UnsafeLock lock = new UnsafeLock(); 26 | 27 | public void method1() { 28 | lock.lock(this); 29 | try { 30 | //模拟方法需要执行100毫秒 31 | Thread.sleep(100); 32 | System.out.println("method1() execute!"); 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | } finally { 36 | lock.unlock(this); 37 | } 38 | } 39 | 40 | public void method2() { 41 | lock.lock(this); 42 | System.out.println("method2() execute!"); 43 | lock.unlock(this); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /concurrent/src/main/java/unsafe/UnsafeTest.java: -------------------------------------------------------------------------------- 1 | package unsafe; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import sun.misc.Unsafe; 6 | 7 | import java.io.File; 8 | import java.io.FileInputStream; 9 | import java.lang.reflect.Constructor; 10 | import java.lang.reflect.Field; 11 | import java.lang.reflect.Method; 12 | 13 | /** 14 | * Created by 李恒名 on 2017/6/20. 15 | */ 16 | public class UnsafeTest { 17 | private Unsafe unsafe; 18 | 19 | @Before 20 | public void before() throws Exception { 21 | Field f = Unsafe.class.getDeclaredField("theUnsafe"); 22 | f.setAccessible(true); 23 | unsafe = (Unsafe) f.get(null); 24 | } 25 | 26 | /** 27 | * 通过反射Constructor获得Unsafe的实例对象 28 | * 29 | * @throws Exception 30 | */ 31 | @Test 32 | public void test1() throws Exception { 33 | Constructor constructor = Unsafe.class.getDeclaredConstructor(); 34 | constructor.setAccessible(true); 35 | Unsafe unsafe = constructor.newInstance(); 36 | System.out.println(unsafe); 37 | } 38 | 39 | /** 40 | * 通过反射Field获得Unsafe的实例对象 41 | * 42 | * @throws Exception 43 | */ 44 | @Test 45 | public void test2() throws Exception { 46 | Field f = Unsafe.class.getDeclaredField("theUnsafe"); 47 | f.setAccessible(true); 48 | Unsafe unsafe = (Unsafe) f.get(null); 49 | System.out.println(unsafe); 50 | } 51 | 52 | /** 53 | * 通过Unsafe的defineClass方法在内存中创建一个Class对象 54 | * 55 | * @throws Exception 56 | */ 57 | @Test 58 | public void test3() throws Exception { 59 | //读取Class文件 60 | File file = new File("E:\\classes\\Test.class"); 61 | FileInputStream input = new FileInputStream(file); 62 | byte[] data = new byte[(int) file.length()]; 63 | input.read(data); 64 | input.close(); 65 | //创建Class对象 66 | //Class clazz = unsafe.defineClass("Test", data, 0, data.length);//这个方法在Java 8 没了。 67 | Class clazz = unsafe.defineClass("Test", data, 0, data.length, null, null); 68 | //通过反射创建示例调用方法 69 | Object instance = clazz.newInstance(); 70 | Method method = clazz.getMethod("say", null); 71 | method.invoke(instance);//Hello 72 | } 73 | 74 | /** 75 | * 通过Unsafe的allocateInstance方法创建一个类的实例 76 | * 77 | * @throws Exception 78 | */ 79 | @Test 80 | public void test4() throws Exception { 81 | //通过Unsafe创建实例 82 | TestClass instanceByUnsafe = (TestClass) unsafe.allocateInstance(TestClass.class); 83 | instanceByUnsafe.printValue();//0 84 | 85 | //通过反射创建实例 86 | //TestClass instanceByReflect = TestClass.class.newInstance();//该方法只能实例化拥有公开无参构造器的类 87 | Constructor constructor = TestClass.class.getDeclaredConstructor(); 88 | constructor.setAccessible(true);//访问私有构造 89 | TestClass instanceByReflect = constructor.newInstance();//创建实例 90 | instanceByReflect.printValue();//1 91 | } 92 | 93 | @Test 94 | public void test5() throws Exception { 95 | unsafe.allocateMemory(Long.MAX_VALUE);//java.lang.OutOfMemoryError 96 | } 97 | 98 | @Test 99 | public void test6() throws Exception { 100 | Object lock = new Object(); 101 | //注掉下面这行代码则抛出java.lang.IllegalMonitorStateException 102 | unsafe.monitorEnter(lock); 103 | lock.wait(1000); 104 | System.out.println("Hello World"); 105 | unsafe.monitorExit(lock); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /concurrent/src/main/java/volatiles/Singleton.java: -------------------------------------------------------------------------------- 1 | package volatiles; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/15. 5 | */ 6 | public class Singleton { 7 | private volatile static Singleton instance; 8 | 9 | private Singleton() { 10 | new AssertionError("don't support reflect."); 11 | } 12 | 13 | public static Singleton getInstance() { 14 | if (instance == null) { // Single Checked 15 | synchronized (Singleton.class) { 16 | if (instance == null) { // Double checked 17 | instance = new Singleton(); 18 | } 19 | } 20 | } 21 | return instance; 22 | } 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /concurrent/src/main/java/volatiles/VolatileTest.java: -------------------------------------------------------------------------------- 1 | package volatiles; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/14. 5 | */ 6 | public class VolatileTest { 7 | 8 | private /*volatile*/ int sharedValue = 0; 9 | 10 | public static void main(String[] args) throws InterruptedException { 11 | VolatileTest test = new VolatileTest(); 12 | new Thread(() -> test.listener()).start(); 13 | new Thread(() -> test.increment()).start(); 14 | 15 | /** 16 | 输出: 17 | Value Incrementing:1 18 | Value Incrementing:2 19 | Value Incrementing:3 20 | Value Incrementing:4 21 | Value Incrementing:5 22 | 使用 volatile 修饰 sharedValue后: 23 | Value Incrementing:1 24 | Value Changed:1 25 | Value Incrementing:2 26 | Value Changed:2 27 | Value Incrementing:3 28 | Value Changed:3 29 | Value Incrementing:4 30 | Value Changed:4 31 | Value Incrementing:5 32 | Value Changed:5 33 | */ 34 | } 35 | 36 | public void listener() { 37 | int localValue = sharedValue; 38 | while (sharedValue < 5) { 39 | if (localValue != sharedValue) { 40 | System.out.println("Value Changed:" + sharedValue); 41 | localValue = sharedValue; 42 | } 43 | } 44 | } 45 | 46 | public void increment() { 47 | while (sharedValue < 5) { 48 | try { 49 | Thread.sleep(500); 50 | } catch (InterruptedException e) { 51 | e.printStackTrace(); 52 | } 53 | ++sharedValue; 54 | System.out.println("Value Incrementing:" + sharedValue); 55 | 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /container/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | java-codes 7 | com.github.lihengming 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | container 13 | 14 | 15 | -------------------------------------------------------------------------------- /data-structure-algorithm/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | java-codes 7 | com.github.lihengming 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | data-structure-algorithm 13 | 14 | 15 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/arithmetic/BinarySearch.java: -------------------------------------------------------------------------------- 1 | package arithmetic; 2 | 3 | import org.junit.Assert; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | * Created by 李恒名 on 2017/6/23. 9 | */ 10 | public class BinarySearch { 11 | 12 | public static int indexOf(int[] arr, int key) { 13 | int low = 0; 14 | int high = arr.length - 1; 15 | while (low <= high) { 16 | int mid = (low + high) >>> 1;//取中间索引 17 | long midVal = arr[mid]; 18 | 19 | if (midVal < key)//如果中间值小于key值则key在高位 20 | low = mid + 1; 21 | else if (midVal > key)//如果中间值大于key值则key在低位 22 | high = mid - 1; 23 | else 24 | return mid; // 找到,返回索引位置 25 | 26 | } 27 | return -1; // 没有找到,返回 -1 28 | } 29 | 30 | public static void main(String[] args) { 31 | int[] arr = {9, 6, 7, 4, 5, 3, 2, 1}; 32 | //需先将待搜索的数组进行排序 33 | Arrays.sort(arr);//[1, 2, 3, 4, 5, 6, 7, 9] 34 | Assert.assertEquals(indexOf(arr, 6), 5); 35 | 36 | Assert.assertEquals(indexOf(arr, 8), -1); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/arithmetic/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package arithmetic; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/15. 7 | *

8 | * 冒泡排序 9 | */ 10 | public class BubbleSort { 11 | 12 | public static void sort(int[] arr) { 13 | for (int i = 0; i < arr.length - 1; i++) { 14 | for (int j = 0; j < arr.length - i - 1; j++) { 15 | if (arr[j] > arr[j + 1]) { 16 | int temp = arr[j]; 17 | arr[j] = arr[j + 1]; 18 | arr[j + 1] = temp; 19 | } 20 | } 21 | System.out.println("第" + (i + 1) + "轮排序结果:" + Arrays.toString(arr)); 22 | } 23 | } 24 | 25 | public static void main(String[] args) { 26 | int[] arr = {9, 6, 7, 4, 5, 3, 2, 1}; 27 | sort(arr); 28 | System.out.println(Arrays.toString(arr)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/arithmetic/HeapSort.java: -------------------------------------------------------------------------------- 1 | package arithmetic; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/15. 7 | *

8 | * 堆排序,对简单选择排序的优化。 9 | * 1. 将序列构建成大顶堆。 10 | * 2. 将根节点与最后一个节点交换,然后断开最后一个节点。 11 | * 3. 重复第一、二步,直到所有节点断开 12 | */ 13 | public class HeapSort { 14 | public static void sort(int[] arr) { 15 | int arrayLength = arr.length; 16 | //循环建堆 17 | for (int i = 0; i < arrayLength - 1; i++) { 18 | //建堆 19 | buildMaxHeap(arr, arrayLength - 1 - i); 20 | //交换堆顶和最后一个元素 21 | swap(arr, 0, arrayLength - 1 - i); 22 | System.out.println("第" + (i + 1) + "轮排序结果:" + Arrays.toString(arr)); 23 | } 24 | } 25 | 26 | private static void swap(int[] data, int i, int j) { 27 | int tmp = data[i]; 28 | data[i] = data[j]; 29 | data[j] = tmp; 30 | } 31 | 32 | //对data数组从0到lastIndex建大顶堆 33 | private static void buildMaxHeap(int[] data, int lastIndex) { 34 | //从lastIndex处节点(最后一个节点)的父节点开始 35 | for (int i = (lastIndex - 1) / 2; i >= 0; i--) { 36 | //k保存正在判断的节点 37 | int k = i; 38 | //如果当前k节点的子节点存在 39 | while (k * 2 + 1 <= lastIndex) { 40 | //k节点的左子节点的索引 41 | int biggerIndex = 2 * k + 1; 42 | //如果biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在 43 | if (biggerIndex < lastIndex) { 44 | //若果右子节点的值较大 45 | if (data[biggerIndex] < data[biggerIndex + 1]) { 46 | //biggerIndex总是记录较大子节点的索引 47 | biggerIndex++; 48 | } 49 | } 50 | //如果k节点的值小于其较大的子节点的值 51 | if (data[k] < data[biggerIndex]) { 52 | //交换他们 53 | swap(data, k, biggerIndex); 54 | //将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值 55 | k = biggerIndex; 56 | } else { 57 | break; 58 | } 59 | } 60 | } 61 | } 62 | 63 | public static void main(String[] args) { 64 | int[] arr = {9, 6, 7, 4, 5, 3, 2, 1}; 65 | sort(arr); 66 | System.out.println(Arrays.toString(arr)); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/arithmetic/InsertSort.java: -------------------------------------------------------------------------------- 1 | package arithmetic; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/15. 7 | */ 8 | public class InsertSort { 9 | public static void sort(int[] arr) { 10 | int length = arr.length;//数组长度,将这个提取出来是为了提高速度。 11 | int insertNum;//要插入的数 12 | for (int i = 1; i < length; i++) {//插入的次数 13 | insertNum = arr[i];//要插入的数 14 | int j = i - 1;//已经排序好的序列元素个数 15 | while (j >= 0 && arr[j] > insertNum) {//序列从后到前循环,将大于insertNum的数向后移动一格 16 | arr[j + 1] = arr[j];//元素移动一格 17 | j--; 18 | } 19 | arr[j + 1] = insertNum;//将需要插入的数放在要插入的位置。 20 | } 21 | } 22 | 23 | public static void main(String[] args) { 24 | int[] arr = {9, 6, 7, 4, 5, 3, 2, 1}; 25 | sort(arr); 26 | System.out.println(Arrays.toString(arr)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/arithmetic/QuickSort.java: -------------------------------------------------------------------------------- 1 | package arithmetic; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/15. 7 | */ 8 | public class QuickSort { 9 | 10 | public static void sort(int[] arr, int start, int end) { 11 | if (start < end) { 12 | int base = arr[start]; // 选定的基准值(第一个数值作为基准值) 13 | int temp; // 记录临时中间值 14 | int i = start, j = end; 15 | do { 16 | while ((arr[i] < base) && (i < end)) 17 | i++; 18 | while ((arr[j] > base) && (j > start)) 19 | j--; 20 | if (i <= j) { 21 | temp = arr[i]; 22 | arr[i] = arr[j]; 23 | arr[j] = temp; 24 | i++; 25 | j--; 26 | } 27 | } while (i <= j); 28 | if (start < j) 29 | sort(arr, start, j); 30 | if (end > i) 31 | sort(arr, i, end); 32 | } 33 | } 34 | 35 | public static void main(String[] args) { 36 | int[] arr = {9, 6, 7, 4, 5, 3, 2, 1}; 37 | sort(arr, 0, arr.length - 1); 38 | System.out.println(Arrays.toString(arr)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/arithmetic/SelectSort.java: -------------------------------------------------------------------------------- 1 | package arithmetic; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/15. 7 | */ 8 | public class SelectSort { 9 | public static void sort(int[] arr) { 10 | for (int i = 0; i < arr.length; i++) {//循环次数 11 | int key = arr[i]; 12 | int position = i; 13 | for (int j = i + 1; j < arr.length; j++) {//选出最小的值和位置 14 | if (arr[j] < key) { 15 | key = arr[j]; 16 | position = j; 17 | } 18 | } 19 | arr[position] = arr[i];//交换位置 20 | arr[i] = key; 21 | } 22 | } 23 | 24 | public static void main(String[] args) { 25 | int[] arr = {9, 6, 7, 4, 5, 3, 2, 1}; 26 | sort(arr); 27 | System.out.println(Arrays.toString(arr)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/arithmetic/ShellSort.java: -------------------------------------------------------------------------------- 1 | package arithmetic; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/15. 7 | */ 8 | public class ShellSort { 9 | 10 | public static void sort(int[] arr) { 11 | int len = arr.length; 12 | while (len != 0) { 13 | len = len / 2; 14 | for (int x = 0; x < len; x++) {//分的组数 15 | for (int i = x + len; i < arr.length; i += len) {//组中的元素,从第二个数开始 16 | int j = i - len;//j为有序序列最后一位的位数 17 | int temp = arr[i];//要插入的元素 18 | for (; j >= 0 && temp < arr[j]; j -= len) {//从后往前遍历。 19 | arr[j + len] = arr[j];//向后移动len位 20 | } 21 | arr[j + len] = temp; 22 | } 23 | } 24 | } 25 | } 26 | 27 | public static void main(String[] args) { 28 | int[] arr = {9, 6, 7, 4, 5, 3, 2, 1}; 29 | sort(arr); 30 | System.out.println(Arrays.toString(arr)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/data/structure/queue/Queue.java: -------------------------------------------------------------------------------- 1 | package data.structure.queue; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/15. 5 | * 6 | * 队列(Queue),是先进先出(FIFO, First-In-First-Out)的线性表 7 | */ 8 | public interface Queue { 9 | 10 | void enQueue(Object element); 11 | 12 | Object deQueue(); 13 | } 14 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/data/structure/queue/QueueLinkedImpl.java: -------------------------------------------------------------------------------- 1 | package data.structure.queue; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/23. 5 | *

6 | * 保存指向首尾节点的指针,每次从链表尾插入,从链表头删除。 7 | */ 8 | public class QueueLinkedImpl implements Queue { 9 | private Node first, last; 10 | 11 | private class Node { 12 | private Node next; 13 | private Object element; 14 | } 15 | 16 | @Override 17 | public void enQueue(Object element) { 18 | Node oldLast = last; 19 | last = new Node(); 20 | last.element = element; 21 | last.next = null; 22 | if (first == null) { 23 | first = last; 24 | } else { 25 | //2017年7月26日17:28:33 原始链表尾的next指针指向新加的节点 26 | oldLast.next = last; 27 | } 28 | 29 | } 30 | 31 | @Override 32 | public Object deQueue() { 33 | Object element = first.element; 34 | first = first.next; 35 | if (first == null) last = null; 36 | return element; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/data/structure/queue/Tester.java: -------------------------------------------------------------------------------- 1 | package data.structure.queue; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/8. 7 | */ 8 | public class Tester { 9 | 10 | 11 | //测试队列的链表实现 12 | @Test 13 | public void test2(){ 14 | Queue queue = new QueueLinkedImpl(); 15 | 16 | queue.enQueue("1"); 17 | queue.enQueue("2"); 18 | queue.enQueue("3"); 19 | 20 | System.out.println(queue.deQueue()); 21 | System.out.println(queue.deQueue()); 22 | System.out.println(queue.deQueue()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/data/structure/stack/Stack.java: -------------------------------------------------------------------------------- 1 | package data.structure.stack; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/8. 5 | *

6 | * 后进先出(LIFO, Last In First Out) 7 | */ 8 | public interface Stack { 9 | //入栈 10 | void push(Object element); 11 | 12 | //出栈 13 | Object pop(); 14 | } 15 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/data/structure/stack/StackArrayImpl.java: -------------------------------------------------------------------------------- 1 | package data.structure.stack; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/8. 5 | */ 6 | public class StackArrayImpl implements Stack { 7 | 8 | private Object[] array; 9 | private int index = 0; 10 | 11 | public StackArrayImpl(int size) { 12 | this.array = new Object[size]; 13 | } 14 | 15 | @Override 16 | public void push(Object element) { 17 | if(index < array.length){ 18 | array[index++] = element; 19 | }else { 20 | throw new RuntimeException("Stack overflow"); 21 | } 22 | } 23 | 24 | @Override 25 | public Object pop() { 26 | if(index < 1){ 27 | throw new RuntimeException("Stack is empty"); 28 | } 29 | return array[--index]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/data/structure/stack/StackLinkedImpl.java: -------------------------------------------------------------------------------- 1 | package data.structure.stack; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/8. 5 | * 6 | */ 7 | public class StackLinkedImpl implements Stack { 8 | 9 | private Node first = null; 10 | 11 | private class Node{ 12 | private Node next; 13 | private Object element; 14 | } 15 | 16 | @Override 17 | public void push(Object element) { 18 | if(first == null){//如果第一个节点为空创建新节点 19 | Node node = new Node(); 20 | node.element = element; 21 | first = node; 22 | }else {//创建新节点并将其移至链表首部 23 | Node oldFirst = first; 24 | Node node = new Node(); 25 | node.element = element; 26 | first = node; 27 | node.next = oldFirst; 28 | } 29 | } 30 | 31 | @Override 32 | public Object pop() { 33 | if(first == null){ 34 | throw new RuntimeException("Stack is empty"); 35 | } 36 | Object element = first.element;//获取首部节点的元素 37 | first = first.next;//将下一个节点移至链表首部 38 | return element; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /data-structure-algorithm/src/main/java/data/structure/stack/Tester.java: -------------------------------------------------------------------------------- 1 | package data.structure.stack; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/6/8. 7 | */ 8 | public class Tester { 9 | 10 | //测试栈的数组实现 11 | @Test 12 | public void test1(){ 13 | Stack stack = new StackArrayImpl(3); 14 | stack.push("1"); 15 | stack.push("2"); 16 | stack.push("3"); 17 | 18 | System.out.println(stack.pop()); 19 | System.out.println(stack.pop()); 20 | System.out.println(stack.pop()); 21 | } 22 | 23 | //测试栈的链表实现 24 | @Test 25 | public void test2(){ 26 | Stack stack = new StackLinkedImpl(); 27 | stack.push("1"); 28 | stack.push("2"); 29 | stack.push("3"); 30 | 31 | System.out.println(stack.pop()); 32 | System.out.println(stack.pop()); 33 | System.out.println(stack.pop()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /design-pattern/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | java-codes 7 | com.github.lihengming 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | design-pattern 13 | 14 | 15 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/behavioral/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 行为型模式 3 | * 4 | */ 5 | package behavioral; -------------------------------------------------------------------------------- /design-pattern/src/main/java/creational/AbstractFactoryPattern.java: -------------------------------------------------------------------------------- 1 | package creational; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/7/16. 5 | *

6 | * 抽象工厂模式,与简单工厂、工厂方法模式的区别在于,前者只有一个产品线只为创建一个 7 | * 产品服务,而后者则拥有多个产品线。 8 | */ 9 | public class AbstractFactoryPattern { 10 | //汽车抽象 11 | static abstract class Car { 12 | abstract void run(); 13 | } 14 | 15 | //SUV产品抽象 16 | static abstract class Suv extends Car { 17 | } 18 | 19 | //商务轿车产品抽象 20 | static abstract class Sedan extends Car { 21 | } 22 | 23 | //奔驰SUV 24 | static class BenzSuv extends Suv { 25 | @Override 26 | void run() { 27 | System.out.println("奔驰(SUV)车在跑"); 28 | } 29 | } 30 | 31 | //奔驰轿车 32 | static class BenzSedan extends Sedan { 33 | @Override 34 | void run() { 35 | System.out.println("奔驰(轿车)车在跑"); 36 | } 37 | } 38 | 39 | //宝马SUV 40 | static class BMWSuv extends Suv { 41 | @Override 42 | void run() { 43 | System.out.println("宝马(SUV)车在跑"); 44 | } 45 | } 46 | 47 | //宝马轿车 48 | static class BMWSedan extends Sedan { 49 | @Override 50 | void run() { 51 | System.out.println("宝马(轿车)车在跑"); 52 | } 53 | } 54 | 55 | //抽象汽车工厂(拥有两个产品线) 56 | static abstract class CarFactory { 57 | abstract Suv getSuv(); 58 | 59 | abstract Sedan getSedan(); 60 | } 61 | 62 | //奔驰汽车工厂 63 | static class BenzCarFactory extends CarFactory { 64 | 65 | @Override 66 | Suv getSuv() { 67 | return new BenzSuv(); 68 | } 69 | 70 | @Override 71 | Sedan getSedan() { 72 | return new BenzSedan(); 73 | } 74 | } 75 | 76 | //宝马汽车工厂 77 | static class BMWCarFactory extends CarFactory { 78 | 79 | @Override 80 | Suv getSuv() { 81 | return new BMWSuv(); 82 | } 83 | 84 | @Override 85 | Sedan getSedan() { 86 | return new BMWSedan(); 87 | } 88 | } 89 | 90 | public static void main(String[] args) { 91 | CarFactory carFactory = new BenzCarFactory(); 92 | //CarFactory carFactory = new BMWCarFactory(); 93 | Sedan sedan = carFactory.getSedan(); 94 | sedan.run(); 95 | Suv suv = carFactory.getSuv(); 96 | suv.run(); 97 | } 98 | 99 | /** 100 | * 总结: 101 | * 所谓抽象工厂模式就是她提供一个接口,用于创建相关或者依赖对象的家族,而不需要明确 102 | * 指定具体类。他允许客户端使用抽象的接口来创建一组相关的产品,而不需要关系实际产出 103 | * 的具体产品是什么。这样一来,客户就可以从具体的产品中被解耦。它的优点是隔离了具体 104 | * 类的生成,使得客户端不需要知道什么被创建了,而缺点就在于新增新的行为会比较麻烦, 105 | * 因为当添加一个新的产品对象时,需要更加需要更改接口及其下所有子类。 106 | */ 107 | } 108 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/creational/BuilderPattern.java: -------------------------------------------------------------------------------- 1 | package creational; 2 | 3 | /** 4 | * Created by Potato on 2017/7/16. 5 | *

6 | * 创建者模式,当创造一个对象需要很多步骤时适合使用建造者模式。而当只需调用一个方法 7 | * 就可以简单地创建整个对象时适合使用工厂模式。 8 | * @see StringBuilder 9 | * @see StringBuffer 10 | * @see java.sql.PreparedStatement 11 | * @see javax.swing.GroupLayout.Group 12 | */ 13 | public class BuilderPattern { 14 | 15 | /** 16 | * 被创建的对象,以手机为例。 17 | */ 18 | static class Phone { 19 | private String displayScreen;//显示器 20 | private String battery;//电池 21 | private String camera;//摄像头 22 | private String operatingSystem;//操作系统 23 | 24 | public String getDisplayScreen() { 25 | return displayScreen; 26 | } 27 | 28 | public void setDisplayScreen(String displayScreen) { 29 | this.displayScreen = displayScreen; 30 | } 31 | 32 | public String getBattery() { 33 | return battery; 34 | } 35 | 36 | public void setBattery(String battery) { 37 | this.battery = battery; 38 | } 39 | 40 | public String getCamera() { 41 | return camera; 42 | } 43 | 44 | public void setCamera(String camera) { 45 | this.camera = camera; 46 | } 47 | 48 | public String getOperatingSystem() { 49 | return operatingSystem; 50 | } 51 | 52 | public void setOperatingSystem(String operatingSystem) { 53 | this.operatingSystem = operatingSystem; 54 | } 55 | } 56 | 57 | static class PhoneBuilder { 58 | public Phone build(){ 59 | Phone phone = new Phone(); 60 | phone.setBattery("三星电池"); 61 | phone.setCamera("索尼摄像头"); 62 | phone.setDisplayScreen("三星显示器"); 63 | phone.setOperatingSystem("IOS 10 操作系统"); 64 | System.out.println(String.format("手机创建完成,使用%s、%s、%s、%s。", 65 | phone.getBattery(), 66 | phone.getCamera(), 67 | phone.getDisplayScreen(), 68 | phone.getOperatingSystem())); 69 | return phone; 70 | } 71 | } 72 | 73 | public static void main(String[] args) { 74 | PhoneBuilder builder = new PhoneBuilder(); 75 | Phone phone = builder.build(); 76 | //手机创建完成,使用三星电池、索尼摄像头、三星显示器、IOS 10 操作系统。 77 | } 78 | 79 | /** 80 | * 总结: 81 | * 建造者模式将复杂产品的构建过程封装分解在不同的方法中,使得创建过程非常清晰,能够 82 | * 让我们更加精确的控制复杂产品对象的创建过程,同时它隔离了复杂产品对象的创建和使用 83 | * ,使得相同的创建过程能够创建不同的产品。但是如果某个产品的内部结构过于复杂,将会 84 | * 导致整个系统变得非常庞大,不利于控制,同时若几个产品之间存在较大的差异,则不适用 85 | * 建造者模式,毕竟这个世界上存在相同点大的两个产品并不是很多,所以它的使用范围有限。 86 | */ 87 | } 88 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/creational/FactoryMethodPattern.java: -------------------------------------------------------------------------------- 1 | package creational; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/14. 5 | *

6 | * 工厂方法模式 7 | */ 8 | public class FactoryMethodPattern { 9 | //汽车抽象 10 | static abstract class Car { 11 | abstract void run(); 12 | } 13 | //奔驰汽车 14 | static class Benz extends Car { 15 | 16 | @Override 17 | void run() { 18 | System.out.println("奔驰车在跑"); 19 | } 20 | } 21 | //宝马汽车 22 | static class BMW extends Car { 23 | 24 | @Override 25 | void run() { 26 | System.out.println("宝马车在跑"); 27 | } 28 | } 29 | //抽象的汽车工厂 30 | static abstract class CarFactory { 31 | public abstract Car getCar(); 32 | } 33 | //奔驰汽车工厂 34 | static class BenzFactory extends CarFactory { 35 | @Override 36 | public Car getCar() { 37 | return new Benz(); 38 | } 39 | } 40 | //宝马汽车工厂 41 | static class BMWFactory extends CarFactory { 42 | @Override 43 | public Car getCar() { 44 | return new BMW(); 45 | } 46 | } 47 | public static void main(String[] args) { 48 | CarFactory factory = new BenzFactory(); 49 | //CarFactory factory = new BMWFactory(); 50 | Car car = factory.getCar(); 51 | car.run(); 52 | } 53 | 54 | /** 55 | * 总结: 56 | * 作为抽象工厂模式的孪生兄弟,工厂方法模式定义了一个创建对象的接口,但由子类决定要 57 | * 实例化的类是哪一个,也就是说工厂方法模式让实例化推迟到子类。 58 | * 59 | * 工厂方法模式非常符合“开闭原则”,当需要增加一个新的产品时,我们只需要增加一个具 60 | * 体的产品类和与之对应的具体工厂即可,无须修改原有系统。同时在工厂方法模式中用户只 61 | * 需要知道生产产品的具体工厂即可,无须关系产品的创建过程,甚至连具体的产品类名称都 62 | * 不需要知道。虽然他很好的符合了“开闭原则”,但是由于每新增一个新产品时就需要增加 63 | * 两个类,这样势必会导致系统的复杂度增加。 64 | */ 65 | } 66 | 67 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/creational/PrototypePattern.java: -------------------------------------------------------------------------------- 1 | package creational; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/7/16. 5 | *

6 | * 原型模式,即通过一个实例的原型来复制(克隆)出类似的实例,而不是去重新创建,这有 7 | * 点像克隆人。如果你使用过 Javascript ,你应该对 Prototype 很熟悉。 8 | */ 9 | public class PrototypePattern { 10 | 11 | /** 12 | * 简单来说就是通过实现 Cloneable 接口来进行复制,这种复制方式为浅复制。 13 | * 14 | * @see Cloneable 15 | */ 16 | static class Man implements Cloneable { 17 | private String name = "高富帅"; 18 | 19 | @Override 20 | protected Man clone() throws CloneNotSupportedException { 21 | return (Man) super.clone(); 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "Man{" + 27 | "name='" + name + '\'' + 28 | '}'; 29 | } 30 | } 31 | 32 | public static void main(String[] args) throws CloneNotSupportedException { 33 | Man man = new Man(); 34 | System.out.println(man); 35 | System.out.println(man.clone()); 36 | System.out.println(man.clone()); 37 | System.out.println(man.clone()); 38 | } 39 | 40 | /** 41 | * 总结: 42 | * 在开发过程中,有时会遇到为一个类创建多个实例的情况,这些实例内部成员往往完 43 | * 全相同或有细微的差异,而且实例的创建开销比较大或者需要输入较多参数,如果能通过复 44 | * 制一个已创建的对象实例来重复创建多个相同的对象,这就可以大大减少创建对象的开销, 45 | * 这个时候就需要原型模式。 46 | */ 47 | } 48 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/creational/SimpleFactoryPattern.java: -------------------------------------------------------------------------------- 1 | package creational; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/14. 5 | *

6 | * 简单工厂模式,简单来说就是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(该模式并不属于GOF 23) 7 | */ 8 | public class SimpleFactoryPattern { 9 | //汽车抽象 10 | static abstract class Car { 11 | abstract void run(); 12 | } 13 | //奔驰汽车 14 | static class Benz extends Car { 15 | @Override 16 | void run() { 17 | System.out.println("奔驰车在跑"); 18 | } 19 | } 20 | //宝马汽车 21 | static class BMW extends Car { 22 | @Override 23 | void run() { 24 | System.out.println("宝马车在跑"); 25 | } 26 | } 27 | //汽车工厂,根据汽车名称创建汽车 28 | static class CarFactory { 29 | Car getCar(String name) { 30 | if (name.equals("Benz")) { 31 | return new Benz(); 32 | } else if (name.equals("BMW")) { 33 | return new BMW(); 34 | } else { 35 | throw new IllegalArgumentException("No support this car"); 36 | } 37 | } 38 | } 39 | 40 | public static void main(String[] args) { 41 | CarFactory factory = new CarFactory(); 42 | Car car = factory.getCar("Benz"); 43 | //Car car = factory.getCar("BMW"); 44 | car.run(); 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/creational/SingletonPattern.java: -------------------------------------------------------------------------------- 1 | package creational; 2 | 3 | import org.junit.Assert; 4 | 5 | import java.util.Objects; 6 | 7 | /** 8 | * Created by 李恒名 on 2017/7/15. 9 | *

10 | * 单例模式,即一个类只允许存在一个实例。 11 | * 12 | * @see java.lang.Runtime#getRuntime() 13 | */ 14 | public class SingletonPattern { 15 | /** 16 | * 懒汉式,线程不安全,在使用时初始化示例(懒加载) 17 | */ 18 | static class Singleton1 { 19 | private static Singleton1 instance; 20 | 21 | private Singleton1() { 22 | new AssertionError("don't support reflect."); 23 | } 24 | 25 | public static Singleton1 getInstance() { 26 | if (instance == null) { 27 | instance = new Singleton1(); 28 | } 29 | return instance; 30 | } 31 | } 32 | 33 | /** 34 | * 懒汉式,线程安全,在使用时初始化示例(懒加载) 35 | */ 36 | static class Singleton2 { 37 | private static Singleton2 instance; 38 | 39 | private Singleton2() { 40 | new AssertionError("don't support reflect."); 41 | } 42 | 43 | public static synchronized Singleton2 getInstance() { 44 | if (instance == null) { 45 | instance = new Singleton2(); 46 | } 47 | return instance; 48 | } 49 | } 50 | 51 | /** 52 | * 懒汉式线程安全的优化写法,双重检验锁模式(double checked locking pattern) 53 | */ 54 | static class Singleton3 { 55 | private volatile static Singleton3 instance; 56 | 57 | private Singleton3() { 58 | new AssertionError("don't support reflect."); 59 | } 60 | 61 | public static Singleton3 getInstance() { 62 | if (instance == null) { // Single Checked 63 | synchronized (Singleton3.class) { 64 | if (instance == null) { // Double checked 65 | instance = new Singleton3(); 66 | } 67 | } 68 | } 69 | return instance; 70 | } 71 | } 72 | 73 | /** 74 | * 饿汉式 static final field,在类被被类加载器加载时便创建实例 75 | */ 76 | static class Singleton4 { 77 | 78 | private static final Singleton4 instance = new Singleton4(); 79 | 80 | private Singleton4() { 81 | new AssertionError("don't support reflect."); 82 | } 83 | 84 | public static Singleton4 getInstance() { 85 | return instance; 86 | } 87 | } 88 | 89 | /** 90 | * 使用静态内部类 static nested class ,这种方法是《Effective Java》上所推荐的 91 | */ 92 | static class Singleton5 { 93 | private static class SingletonHolder { 94 | private static final Singleton5 INSTANCE = new Singleton5(); 95 | } 96 | 97 | private Singleton5() { 98 | new AssertionError("don't support reflect."); 99 | } 100 | 101 | public static final Singleton5 getInstance() { 102 | return SingletonHolder.INSTANCE; 103 | } 104 | } 105 | 106 | /** 107 | * 使用枚举,这也是单例模式最简单的实现 ,这种方法也是《Effective Java》上所推荐的 108 | */ 109 | public enum Singleton6 { 110 | INSTANCE; 111 | } 112 | 113 | public static void main(String[] args) { 114 | Assert.assertTrue(Objects.equals(Singleton1.getInstance(), Singleton1.getInstance())); 115 | Assert.assertTrue(Objects.equals(Singleton1.getInstance(), Singleton1.getInstance())); 116 | Assert.assertTrue(Objects.equals(Singleton2.getInstance(), Singleton2.getInstance())); 117 | Assert.assertTrue(Objects.equals(Singleton3.getInstance(), Singleton3.getInstance())); 118 | Assert.assertTrue(Objects.equals(Singleton4.getInstance(), Singleton4.getInstance())); 119 | Assert.assertTrue(Objects.equals(Singleton5.getInstance(), Singleton5.getInstance())); 120 | Assert.assertTrue(Objects.equals(Singleton6.INSTANCE, Singleton6.INSTANCE)); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/creational/StaticFactoryMethodPattern.java: -------------------------------------------------------------------------------- 1 | package creational; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/6/14. 5 | *

6 | * 静态工厂方法模式,准确来讲这并不是一种设计模式,只是为了简化创建对象的过程。 7 | * 这种创建对象形式很常见,比如 Guava 中的 Lists 、Maps 等。 8 | */ 9 | public class StaticFactoryMethodPattern { 10 | //汽车抽象 11 | static abstract class Car { 12 | abstract void run(); 13 | } 14 | 15 | //奔驰汽车 16 | static class Benz extends Car { 17 | @Override 18 | void run() { 19 | System.out.println("奔驰车在跑"); 20 | } 21 | } 22 | 23 | //宝马汽车 24 | static class BMW extends Car { 25 | @Override 26 | void run() { 27 | System.out.println("宝马车在跑"); 28 | } 29 | } 30 | 31 | //汽车工厂 32 | static final class CarFactory { 33 | 34 | public static Benz getBeznCar() { 35 | return new Benz(); 36 | } 37 | public static BMW getBMWCar() { 38 | return new BMW(); 39 | } 40 | } 41 | 42 | public static void main(String[] args) { 43 | Car car = CarFactory.getBeznCar(); 44 | //Car car = CarFactory.getBMWCar; 45 | car.run(); 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/creational/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 创建型模式 3 | *

4 | * 在软件工程中,创建型模式是处理对象创建的设计模式,试图根据实际情况使用 5 | * 合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设 6 | * 计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。 7 | *

8 | * 创建型模式由两个主导思想构成。一是将系统使用的具体类封装起来,二是隐藏 9 | * 这些具体类的实例创建和结合的方式。 10 | *

11 | * 创建型模式又分为对象创建型模式和类创建型模式。对象创建型模式处理对象的 12 | * 创建,类创建型模式处理类的创建。详细地说,对象创建型模式把对象创建的一 13 | * 部分推迟到另一个对象中,而类创建型模式将它对象的创建推迟到子类中。 14 | */ 15 | package creational; -------------------------------------------------------------------------------- /design-pattern/src/main/java/structural/AdapterPattern.java: -------------------------------------------------------------------------------- 1 | package structural; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * Created by 李恒名 on 2017/7/27. 7 | *

8 | * 适配器模式,用于将一个类的接口转换成客户端所期待的另一种接口。 9 | */ 10 | public class AdapterPattern { 11 | 12 | ////////////////////////////////////////////////////////////////////// 13 | // 类适配器 // 14 | ////////////////////////////////////////////////////////////////////// 15 | 16 | //被适配的源对象(Adaptee) 17 | static class Power_220V { 18 | public void in() { 19 | System.out.print("220V电流输入"); 20 | } 21 | } 22 | 23 | //目标接口(Target) 24 | interface Power_5V { 25 | void in(); 26 | } 27 | 28 | //适配器(Adapter),电源适配器为例 29 | static class PowerAdapter extends Power_220V implements Power_5V { 30 | @Override 31 | public void in() { 32 | System.out.print("5V电流输入"); 33 | System.out.print("("); 34 | super.in(); 35 | System.out.print(")"); 36 | } 37 | } 38 | 39 | //客户端,手机为例 40 | static class Iphone { 41 | 42 | public void charge(Power_5V power) { 43 | System.out.print("充电中..."); 44 | power.in(); 45 | } 46 | } 47 | 48 | @Test 49 | public void testClassAdapter() { 50 | Iphone iPhone = new Iphone(); 51 | PowerAdapter powerAdapter = new PowerAdapter(); 52 | iPhone.charge(powerAdapter); 53 | //充电中...5V电流输入(220V电流输入) 54 | } 55 | 56 | ////////////////////////////////////////////////////////////////////// 57 | // 对象适配器 // 58 | ////////////////////////////////////////////////////////////////////// 59 | 60 | //适配器(Adapter),电源适配器为例 61 | static class PowerAdapter2 implements Power_5V { 62 | 63 | private Power_220V power_220V; 64 | 65 | public PowerAdapter2(Power_220V power_220V) { 66 | this.power_220V = power_220V; 67 | } 68 | 69 | @Override 70 | public void in() { 71 | System.out.print("5V电流输入"); 72 | System.out.print("("); 73 | power_220V.in(); 74 | System.out.print(")"); 75 | } 76 | } 77 | 78 | @Test 79 | public void testObjectAdapter() { 80 | Iphone iPhone = new Iphone(); 81 | PowerAdapter2 powerAdapter = new PowerAdapter2(new Power_220V()); 82 | iPhone.charge(powerAdapter); 83 | //充电中...5V电流输入(220V电流输入) 84 | } 85 | 86 | 87 | ////////////////////////////////////////////////////////////////////// 88 | // 接口适配器 // 89 | ////////////////////////////////////////////////////////////////////// 90 | 91 | /** 92 | * 有时候,我们需要实现一个接口,但只想实现其中一部分方法,又不 93 | * 想出现很多空的实现方法(这会让代码不那么优美),这时候就便可 94 | * 以使用接口适配器,把那些空的实现方法放在适配器内,去重写那些 95 | * 我们真正要实现的方法即可。 96 | *

97 | * 如果你使用过 Spring MVC,你应该对下面这两个接口适配器很熟悉 98 | *

99 | * - WebMvcConfigurerAdapter 100 | * - HandlerInterceptorAdapter 101 | */ 102 | 103 | //源接口 104 | interface Source { 105 | void method1(); 106 | 107 | void method2(); 108 | 109 | void method3(); 110 | } 111 | 112 | //接口适配器 113 | static abstract class SourceAdapter implements Source { 114 | @Override 115 | public void method1() {} 116 | @Override 117 | public void method2() { } 118 | @Override 119 | public void method3() { } 120 | } 121 | 122 | //继承适配器,重写 method1 123 | static class SourceImpl extends SourceAdapter { 124 | @Override 125 | public void method1() { 126 | System.out.println("method1 impl"); 127 | } 128 | } 129 | 130 | /** 131 | * 总结: 132 | * 在我们的应用程序中我们可能需要将两个不同接口的类来进行通信,在不修改这两个的前提 133 | * 下我们可能会需要某个中间件来完成这个衔接的过程。这个中间件就是适配器。所谓适配器 134 | * 模式就是将一个类的接口,转换成客户期望的另一个接口。它可以让原本两个不兼容的接口 135 | * 能够无缝完成对接。 136 | */ 137 | 138 | } 139 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/structural/BridgePattern.java: -------------------------------------------------------------------------------- 1 | package structural; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/10/06. 5 | * 6 | * 桥接模式的意图是将抽象类与抽象方法的实现相互分离来实现解耦,以便二者可以相互独立地变化。 7 | * 8 | * 比如太阳镜,太阳镜有很多种品牌,不管何种品牌它们都会提供不同的风格供顾客选择,比如复古 9 | * 风格、飞行员风格等,太阳镜与风格间的关系便可使用该模式来维护。 10 | */ 11 | public class BridgePattern { 12 | //太阳镜的抽象类 13 | static abstract class SunGlasses { 14 | protected Style style; 15 | 16 | protected SunGlasses(Style style) { 17 | this.style = style; 18 | } 19 | 20 | //获取品牌名称 21 | abstract String getBrandName(); 22 | 23 | //戴眼镜 24 | public void putOn() { 25 | System.out.println("戴上" + getBrandName() + "-" + style.getStyle() + "风格的太阳镜"); 26 | } 27 | } 28 | 29 | static class BolonSunGlasses extends SunGlasses { 30 | public BolonSunGlasses(Style style) { 31 | super(style); 32 | } 33 | 34 | @Override 35 | String getBrandName() { 36 | return "暴龙"; 37 | } 38 | } 39 | 40 | static class DiorSunGlasses extends SunGlasses { 41 | public DiorSunGlasses(Style style) { 42 | super(style); 43 | } 44 | 45 | @Override 46 | String getBrandName() { 47 | return "迪奥"; 48 | } 49 | } 50 | 51 | //太阳镜风格接口 52 | interface Style { 53 | String getStyle(); 54 | } 55 | 56 | //复古风格 57 | static class RetroStyle implements Style { 58 | 59 | @Override 60 | public String getStyle() { 61 | return "复古"; 62 | } 63 | } 64 | 65 | //飞行员风格 66 | static class PilotStyle implements Style { 67 | 68 | @Override 69 | public String getStyle() { 70 | return "飞行员"; 71 | } 72 | } 73 | 74 | public static void main(String[] args) { 75 | RetroStyle retroStyle = new RetroStyle(); 76 | PilotStyle pilotStyle = new PilotStyle(); 77 | 78 | SunGlasses glasses = new DiorSunGlasses(retroStyle); 79 | glasses.putOn(); 80 | //戴上迪奥-复古风格的太阳镜 81 | glasses = new DiorSunGlasses(pilotStyle); 82 | glasses.putOn(); 83 | //戴上迪奥-飞行员风格的太阳镜 84 | glasses = new BolonSunGlasses(pilotStyle); 85 | glasses.putOn(); 86 | //戴上暴龙-飞行员风格的太阳镜 87 | } 88 | 89 | /** 90 | * 总结: 91 | * 如果说某个系统能够从多个角度来进行分类,且每一种分类都可能会变化,那么我们需要做 92 | * 的就是讲这多个角度分离出来,使得他们能独立变化,减少他们之间的耦合,这个分离过 93 | * 程就使用了桥接模式。所谓桥接模式就是讲抽象部分和实现部分隔离开来,使得他们能够 94 | * 独立变化。桥接模式将继承关系转化成关联关系,封装了变化,完成了解耦,减少了系统 95 | * 中类的数量,也减少了代码量。 96 | */ 97 | } 98 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/structural/DecoratorPattern.java: -------------------------------------------------------------------------------- 1 | package structural; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/7/27. 5 | *

6 | * 装饰者模式 7 | * 8 | * @see java.io.InputStream 抽象构件 9 | * @see java.io.FilterInputStream 抽象装饰类 10 | * @see java.io.BufferedInputStream 具体的装饰类 11 | * @see java.io.DataInputStream 具体的装饰类 12 | */ 13 | public class DecoratorPattern { 14 | //抽象构件(Component) 15 | static abstract class Man { 16 | abstract void aboutMe(); 17 | } 18 | 19 | //具体的构件(ConcreteComponent) 20 | static class Potato extends Man { 21 | 22 | @Override 23 | public void aboutMe() { 24 | System.out.print("Hi,我是土豆"); 25 | } 26 | } 27 | 28 | //抽象装饰类(Decorator) 29 | static abstract class Decorator extends Man { 30 | private Man man; 31 | 32 | protected Decorator(Man man) { 33 | this.man = man; 34 | } 35 | 36 | @Override 37 | public void aboutMe() { 38 | man.aboutMe(); 39 | } 40 | } 41 | 42 | //具体装饰类(ConcreteDecorator) 43 | static class ProgrammerDecorator extends Decorator { 44 | public ProgrammerDecorator(Man man) { 45 | super(man); 46 | } 47 | 48 | @Override 49 | public void aboutMe() { 50 | super.aboutMe(); 51 | System.out.print(",我的职业是程序员"); 52 | } 53 | } 54 | 55 | //具体装饰类(ConcreteDecorator) 56 | static class ReaderDecorator extends Decorator { 57 | public ReaderDecorator(Man man) { 58 | super(man); 59 | } 60 | 61 | @Override 62 | public void aboutMe() { 63 | super.aboutMe(); 64 | System.out.print(",我喜欢读书"); 65 | 66 | } 67 | } 68 | 69 | //具体装饰类(ConcreteDecorator) 70 | static class GitHubDecorator extends Decorator { 71 | public GitHubDecorator(Man man) { 72 | super(man); 73 | } 74 | 75 | @Override 76 | public void aboutMe() { 77 | super.aboutMe(); 78 | System.out.print(",闲暇时我喜欢在 GitHub 上溜达"); 79 | 80 | } 81 | } 82 | 83 | //具体装饰类(ConcreteDecorator) 84 | static class WriterDecorator extends Decorator { 85 | public WriterDecorator(Man man) { 86 | super(man); 87 | } 88 | 89 | @Override 90 | public void aboutMe() { 91 | super.aboutMe(); 92 | System.out.print(",也会去写一些技术文章"); 93 | 94 | } 95 | } 96 | 97 | //具体装饰类(ConcreteDecorator) 98 | public static void main(String[] args) { 99 | Man potato = new Potato(); 100 | potato.aboutMe(); 101 | //Hi,我是土豆 102 | 103 | System.out.println(); 104 | 105 | potato = new WriterDecorator(new GitHubDecorator(new ReaderDecorator(new ProgrammerDecorator(potato)))); 106 | potato.aboutMe(); 107 | //Hi,我是土豆,我的职业是程序员,我喜欢读书,闲暇时我喜欢在 GitHub 上溜达,也会去写一些技术文章 108 | } 109 | 110 | /** 111 | * 总结: 112 | * 装饰者模式,可以动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更加有 113 | * 弹性的替代方案,有效的避免了类爆炸现象的产生。虽然装饰者模式能够动态将责任附加到 114 | * 对象上,但是他会产生许多的细小对象,增加了系统的复杂度。java.io 包可谓是装饰者 115 | * 模式的最佳实践。 116 | */ 117 | } 118 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/structural/FacadePattern.java: -------------------------------------------------------------------------------- 1 | package structural; 2 | 3 | /** 4 | * Created by 李恒名 on 2017/7/17. 5 | *

6 | * 外观模式,也称门面模式,用于为一个复杂的系统提供一个统一、简单的访问入口 7 | */ 8 | public class FacadePattern { 9 | 10 | //系统门面 11 | static class SystemFacade { 12 | void start() { 13 | new SubSystemA().start(); 14 | new SubSystemB().start(); 15 | new SubSystemC().start(); 16 | new SubSystemD().start(); 17 | } 18 | } 19 | 20 | static class SubSystemA { 21 | void start() { 22 | System.out.println("子系统A启动"); 23 | } 24 | } 25 | 26 | static class SubSystemB { 27 | void start() { 28 | System.out.println("子系统B启动"); 29 | } 30 | } 31 | 32 | static class SubSystemC { 33 | void start() { 34 | System.out.println("子系统C启动"); 35 | } 36 | } 37 | 38 | static class SubSystemD { 39 | void start() { 40 | System.out.println("子系统D启动"); 41 | } 42 | } 43 | 44 | public static void main(String[] args) { 45 | SystemFacade facade = new SystemFacade(); 46 | facade.start(); 47 | } 48 | 49 | /** 50 | * 总结: 51 | * 我们都知道类与类之间的耦合越低,那么可复用性就越好,如果两个类不必彼此通信,那么 52 | * 就不要让这两个类发生直接的相互关系,如果需要调用里面的方法,可以通过第三者来转发 53 | * 调用。外观模式非常好的诠释了这段话。外观模式提供了一个统一的接口,用来访问子系统 54 | * 中的一群接口。它让一个应用程序中子系统间的相互依赖关系减少到了最少,它给子系统提 55 | * 供了一个简单、单一的屏障,客户通过这个屏障来与子系统进行通信。 56 | * 通过使用外观模式,使得客户对子系统的引用变得简单了,实现了客户与子系统之间的松耦 57 | * 合,但是它违背了“开闭原则”,因为增加新的子系统可能需要修改外观类或客户端的源代码。 58 | */ 59 | } 60 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/structural/ProxyPattern.java: -------------------------------------------------------------------------------- 1 | package structural; 2 | 3 | import java.lang.reflect.Proxy; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | /** 8 | * Created by 李恒名 on 2017/7/19. 9 | *

10 | * 代理模式,为目标对象创建一个代理对象,其他对象可以通过代理对象来访问目标对象的方法,AOP、拦截器均为该模式的实践。 11 | * 12 | * @see java.lang.reflect.Proxy JDK动态代理 13 | */ 14 | public class ProxyPattern { 15 | //唱歌的能力 16 | interface Singable { 17 | void sing(); 18 | } 19 | 20 | //歌手 21 | static class Singer implements Singable { 22 | 23 | @Override 24 | public void sing() { 25 | System.out.println("歌手唱歌"); 26 | } 27 | } 28 | 29 | //歌手的代理人 30 | static class SingerProxy implements Singable { 31 | //歌手 32 | private Singable singer; 33 | 34 | public SingerProxy(Singable singer) { 35 | this.singer = singer; 36 | } 37 | 38 | @Override 39 | public void sing() { 40 | System.out.println("代理人承接演出"); 41 | System.out.println("代理人布置演出场地"); 42 | singer.sing(); 43 | System.out.println("代理人结算演出费用"); 44 | } 45 | } 46 | 47 | public static void main(String[] args) { 48 | Singer singer = new Singer(); 49 | SingerProxy proxy = new SingerProxy(singer); 50 | proxy.sing(); 51 | 52 | /** 53 | * 代理人承接演出 54 | * 代理人布置演出场地 55 | * 歌手唱歌 56 | * 代理人结算演出费用 57 | */ 58 | 59 | // 如果,代理目标方法较多使用静态代理较为麻烦,可以使用动态代理,下面是使用JDK实 60 | // 现动态代理的方式,这种方式有一个要求,被代理的对象必须实现接口。 61 | 62 | List list = DynamicProxy.proxy(new ArrayList()); 63 | list.add("data"); 64 | list.size(); 65 | list.remove("data"); 66 | 67 | /** 68 | * 前置代理,调用方法:add() 69 | * 后置代理,方法返回:true 70 | * 前置代理,调用方法:size() 71 | * 后置代理,方法返回:1 72 | * 前置代理,调用方法:remove() 73 | * 后置代理,方法返回:true 74 | */ 75 | 76 | // 当然除了JDK 提供的方式外我们也可以使用 CGLIB 来使用动态代理,它不要求代理的对象 77 | // 必须实现接口,这基于ASM 字节码技术。 78 | } 79 | 80 | private static class DynamicProxy { 81 | 82 | public static T proxy(T target) { 83 | 84 | return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), 85 | target.getClass().getInterfaces(), (proxy, method, args) -> { 86 | System.out.println("前置代理,调用方法:" + method.getName()+"()"); 87 | Object result = method.invoke(target, args); 88 | System.out.println("后置代理,方法返回:" + result); 89 | return result; 90 | }); 91 | } 92 | } 93 | 94 | 95 | /** 96 | * 总结: 97 | * 代理模式就是给一个对象提供一个代理,并由代理对象控制对原对象的引用。它使得客户不 98 | * 能直接与真正的目标对象通信。代理对象是目标对象的代表,其他需要与这个目标对象打交 99 | * 道的操作都是和这个代理对象在交涉。代理对象可以在客户端和目标对象之间起到中介的作 100 | * 用,这样起到了的作用和保护了目标对象的,同时也在一定程度上面减少了系统的耦合度。 101 | */ 102 | 103 | 104 | } 105 | -------------------------------------------------------------------------------- /design-pattern/src/main/java/structural/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 结构型模式 3 | *

4 | * 结构型模式主要是用于处理类或者对象的组合,它描述了如何来类或者对象更好的组合起来 5 | * ,是从程序的结构上来解决模块之间的耦合问题。它主要包括适配器模式、桥接模式、组合 6 | * 模式、装饰模式、外观模式、享元模式、代理模式这个七个模式。 7 | */ 8 | package structural; -------------------------------------------------------------------------------- /io/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | java-codes 7 | com.github.lihengming 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | io 13 | 14 | 15 | -------------------------------------------------------------------------------- /io/src/main/java/ReadFile.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.nio.ByteBuffer; 3 | import java.nio.channels.FileChannel; 4 | import java.nio.file.Files; 5 | import java.nio.file.Paths; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by 李恒名 on 2017/6/8. 10 | */ 11 | public class ReadFile { 12 | 13 | public static void read(File file) { 14 | 15 | try (BufferedReader reader = new BufferedReader(new FileReader(file))) { 16 | while (reader.ready()) { 17 | System.out.println(reader.readLine()); 18 | } 19 | } catch (IOException e) { 20 | e.printStackTrace(); 21 | } 22 | } 23 | 24 | public static void readByNIO(File file) { 25 | try (FileChannel channel = new FileInputStream(file).getChannel()) { 26 | ByteBuffer buffer = ByteBuffer.allocate((int) file.length()); 27 | channel.read(buffer); 28 | System.out.println(new String(buffer.array())); 29 | } catch (IOException e) { 30 | e.printStackTrace(); 31 | } 32 | } 33 | 34 | public static void readByNIO2(File file) { 35 | try { 36 | List lines = Files.readAllLines(Paths.get(file.toURI())); 37 | for (String line : lines) { 38 | System.out.println(line); 39 | } 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | public static void main(String[] args) { 46 | File file = new File("README.md"); 47 | 48 | read(file); 49 | 50 | readByNIO(file); 51 | 52 | readByNIO2(file); 53 | 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /jvm/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | java-codes 7 | com.github.lihengming 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jvm 13 | 14 | 15 | -------------------------------------------------------------------------------- /jvm/src/main/java/Test.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 李恒名 on 2017/6/8. 3 | */ 4 | public class Test { 5 | public void say() { 6 | System.out.println("Hello"); 7 | } 8 | } -------------------------------------------------------------------------------- /jvm/src/main/java/classloader/CustomClassLoader.java: -------------------------------------------------------------------------------- 1 | package classloader; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * Created by 李恒名 on 2017/6/8. 10 | */ 11 | public class CustomClassLoader extends ClassLoader { 12 | private final String classesDir; 13 | 14 | public CustomClassLoader(String classesDir) { 15 | this.classesDir = classesDir; 16 | } 17 | 18 | @Override 19 | protected Class findClass(String name) throws ClassNotFoundException { 20 | String fileName = name; 21 | if (fileName.indexOf('.') != -1) { 22 | fileName = fileName.replaceAll("\\.", "\\\\"); 23 | } 24 | fileName = fileName + ".class"; 25 | try { 26 | try (FileInputStream in = new FileInputStream(classesDir + fileName)) { 27 | try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { 28 | byte[] buffer = new byte[1024]; 29 | int len = 0; 30 | while ((len = in.read(buffer)) != -1) { 31 | out.write(buffer,0,len); 32 | } 33 | byte[] data = out.toByteArray(); 34 | return defineClass(name, data, 0, data.length); 35 | } 36 | } 37 | } catch (IOException e) { 38 | throw new ClassNotFoundException(name); 39 | } 40 | } 41 | 42 | public static void main(String[] args) throws ReflectiveOperationException{ 43 | //1. 将Test.java 编译为Test.class 后复制到 E:\classes 下,当然也可以选择其他目录作为类加载器的classpath。 44 | //2. 加载 45 | ClassLoader classLoader = new CustomClassLoader("E:\\classes\\"); 46 | Class clazz = classLoader.loadClass("Test");//如果你的Test在一个包内,需要加上包名,如x.y.z.Test 47 | //3. 通过反射调用say()方法 48 | Object instance = clazz.newInstance(); 49 | Method method = clazz.getMethod("say", null); 50 | method.invoke(instance);//Hello 51 | } 52 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.github.lihengming 8 | java-codes 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | socket 13 | io 14 | jvm 15 | container 16 | concurrent 17 | data-structure-algorithm 18 | codemarks 19 | design-pattern 20 | 21 | 22 | 23 | 24 | 25 | 26 | junit 27 | junit 28 | 4.12 29 | 30 | 31 | 32 | 33 | 34 | 35 | maven-compiler-plugin 36 | 3.1 37 | 38 | 1.8 39 | 1.8 40 | UTF-8 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /shared-resources/README.md: -------------------------------------------------------------------------------- 1 | # Shared Resources 2 | -------------------------------------------------------------------------------- /shared-resources/Spring Boot 1.4.1 中文文档.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/Spring Boot 1.4.1 中文文档.epub -------------------------------------------------------------------------------- /shared-resources/Spring Boot 最佳实践.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/Spring Boot 最佳实践.pdf -------------------------------------------------------------------------------- /shared-resources/Spring Boot 笔记.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/Spring Boot 笔记.docx -------------------------------------------------------------------------------- /shared-resources/Spring Data JPA 1.4.3 中文文档.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/Spring Data JPA 1.4.3 中文文档.pdf -------------------------------------------------------------------------------- /shared-resources/Spring Security 4.1 中文文档.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/Spring Security 4.1 中文文档.pdf -------------------------------------------------------------------------------- /shared-resources/github-images/druid-spring-boot-starter-ide-hint.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/github-images/druid-spring-boot-starter-ide-hint.jpg -------------------------------------------------------------------------------- /shared-resources/github-images/issue-31/step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/github-images/issue-31/step1.png -------------------------------------------------------------------------------- /shared-resources/github-images/issue-31/step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/github-images/issue-31/step2.png -------------------------------------------------------------------------------- /shared-resources/github-images/project-example-youku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/github-images/project-example-youku.png -------------------------------------------------------------------------------- /shared-resources/github-images/project-struct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/github-images/project-struct.png -------------------------------------------------------------------------------- /shared-resources/java.util.concurrent.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/java.util.concurrent.xmind -------------------------------------------------------------------------------- /shared-resources/阿里巴巴Java开发手册V1.2.0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/阿里巴巴Java开发手册V1.2.0.pdf -------------------------------------------------------------------------------- /shared-resources/阿里巴巴Java开发手册V1.3.0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lihengming/java-codes/400faef1742afa66bedc4622e760ed9335c393ee/shared-resources/阿里巴巴Java开发手册V1.3.0.pdf -------------------------------------------------------------------------------- /socket/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | java-codes 7 | com.github.lihengming 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | socket 13 | 14 | 15 | 16 | io.netty 17 | netty 18 | 3.5.2.Final 19 | 20 | 21 | -------------------------------------------------------------------------------- /socket/src/main/java/echo/Client.java: -------------------------------------------------------------------------------- 1 | package echo; 2 | 3 | import java.io.DataInputStream; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | import java.net.Socket; 7 | import java.util.Scanner; 8 | 9 | /** 10 | * Created by 李恒名 on 2017/6/8. 11 | */ 12 | public class Client { 13 | 14 | private static final String HOST = "localhost"; 15 | private static final int SERVER_PORT = 7777; 16 | 17 | 18 | public static void main(String[] args) { 19 | // use java 7 try-with-resource auto close resource. 20 | try (Socket client = new Socket(HOST, SERVER_PORT); 21 | DataInputStream in = new DataInputStream(client.getInputStream()); 22 | DataOutputStream out = new DataOutputStream(client.getOutputStream())) { 23 | 24 | //创建系统输入扫描器,监听键盘输入 25 | Scanner scanner = new Scanner(System.in); 26 | System.out.println("Please input word:"); 27 | while (true){ 28 | //获取键盘输入 29 | String word = scanner.nextLine(); 30 | //发送给Server 31 | out.writeUTF(word); 32 | //接收Server 回应 33 | System.out.println(in.readUTF()); 34 | } 35 | 36 | } catch (IOException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /socket/src/main/java/echo/EchoServer.java: -------------------------------------------------------------------------------- 1 | package echo; 2 | 3 | import java.io.DataInputStream; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | import java.net.ServerSocket; 7 | import java.net.Socket; 8 | 9 | /** 10 | * Created by 李恒名 on 2017/6/8. 11 | * 12 | * 一个Socket入门小例子,将客户端的输入返回给客户端,支持多客户端连接。 13 | */ 14 | public class EchoServer { 15 | private static final int SERVER_PORT = 7777; 16 | 17 | public static void main(String[] args) { 18 | // use java 7 try-with-resource auto close resource. 19 | try (ServerSocket server = new ServerSocket(SERVER_PORT)) { 20 | System.out.println("Server started listening port:" + SERVER_PORT); 21 | //持续接收客户端连接请求 22 | while (true){ 23 | Socket client = server.accept(); 24 | System.out.println("Accept connect client:" + client); 25 | //为每一个Client Socket单独创建一个线程去处理 26 | new Thread(new ClientHandler(client)).start(); 27 | } 28 | 29 | } catch (IOException e) { 30 | e.printStackTrace(); 31 | } 32 | } 33 | 34 | private static class ClientHandler implements Runnable { 35 | 36 | private final Socket client; 37 | 38 | public ClientHandler(Socket client) { 39 | this.client = client; 40 | } 41 | 42 | @Override 43 | public void run() { 44 | try (DataInputStream in = new DataInputStream(client.getInputStream()); 45 | DataOutputStream out = new DataOutputStream(client.getOutputStream())) { 46 | //保持连接,持续监听客户端输入。 47 | while (true) { 48 | out.writeUTF("Server echo:" + in.readUTF()); 49 | out.flush(); 50 | } 51 | } catch (IOException e) { 52 | e.printStackTrace(); 53 | } finally { 54 | try { 55 | client.close(); 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /socket/src/main/java/netty/HelloClient.java: -------------------------------------------------------------------------------- 1 | package netty; 2 | 3 | import org.jboss.netty.bootstrap.ClientBootstrap; 4 | import org.jboss.netty.channel.*; 5 | import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; 6 | 7 | import java.net.InetSocketAddress; 8 | import java.util.concurrent.Executors; 9 | 10 | /** 11 | * Created by 李恒名 on 2017/8/8. 12 | */ 13 | public class HelloClient { 14 | public static void main(String args[]) { 15 | // Client服务启动器 16 | ClientBootstrap bootstrap = new ClientBootstrap( 17 | new NioClientSocketChannelFactory( 18 | Executors.newCachedThreadPool(), 19 | Executors.newCachedThreadPool())); 20 | // 设置一个处理服务端消息和各种消息事件的类(Handler) 21 | bootstrap.setPipelineFactory(() -> Channels.pipeline(new HelloClientHandler())); 22 | // 连接到本地的8000端口的服务端 23 | bootstrap.connect(new InetSocketAddress("127.0.0.1", 8000)); 24 | } 25 | 26 | private static class HelloClientHandler extends SimpleChannelHandler { 27 | 28 | 29 | /** 30 | * 当绑定到服务端的时候触发,打印"Hello world, I am client." 31 | * 32 | * @alia OneCoder 33 | * @author lihzh 34 | */ 35 | @Override 36 | public void channelConnected(ChannelHandlerContext ctx, 37 | ChannelStateEvent e) { 38 | System.out.println("Hello world, I am client."); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /socket/src/main/java/netty/NettyTest.java: -------------------------------------------------------------------------------- 1 | package netty; 2 | 3 | 4 | import org.jboss.netty.bootstrap.ServerBootstrap; 5 | import org.jboss.netty.channel.*; 6 | import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; 7 | 8 | import java.net.InetSocketAddress; 9 | import java.util.concurrent.Executors; 10 | 11 | /** 12 | * Created by 李恒名 on 2017/8/8. 13 | */ 14 | public class NettyTest { 15 | public static void main(String[] args) { 16 | // Server服务启动器 17 | ServerBootstrap bootstrap = new ServerBootstrap( 18 | new NioServerSocketChannelFactory( 19 | Executors.newCachedThreadPool(), 20 | Executors.newCachedThreadPool())); 21 | // 设置一个处理客户端消息和各种消息事件的类(Handler) 22 | bootstrap 23 | .setPipelineFactory(new ChannelPipelineFactory() { 24 | @Override 25 | public ChannelPipeline getPipeline() 26 | throws Exception { 27 | return Channels 28 | .pipeline(new HelloServerHandler()); 29 | } 30 | }); 31 | // 开放8000端口供客户端访问。 32 | bootstrap.bind(new InetSocketAddress(8000)); 33 | } 34 | 35 | private static class HelloServerHandler extends 36 | SimpleChannelHandler { 37 | 38 | /** 39 | * 当有客户端绑定到服务端的时候触发,打印"Hello world, I am server." 40 | * 41 | * @alia OneCoder 42 | * @author lihzh 43 | */ 44 | @Override 45 | public void channelConnected( 46 | ChannelHandlerContext ctx, 47 | ChannelStateEvent e) { 48 | System.out.println("Hello world, I am server."); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /socket/src/main/java/rpc/RpcTest.java: -------------------------------------------------------------------------------- 1 | package rpc; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import static rpc.SimpleRpcFramework.export; 6 | import static rpc.SimpleRpcFramework.use; 7 | 8 | /** 9 | * Created by 李恒名 on 2017/8/17. 10 | */ 11 | public class RpcTest { 12 | private static final String HOST = "localhost"; 13 | private static final int PORT = 8888; 14 | 15 | interface ComputeService { 16 | int sum(int a, int b); 17 | } 18 | 19 | 20 | static class ComputeServiceImpl implements ComputeService { 21 | 22 | @Override 23 | public int sum(int a, int b) { 24 | return a + b; 25 | } 26 | } 27 | 28 | //服务提供者 29 | static class Provider implements Runnable { 30 | @Override 31 | public void run() { 32 | //暴露服务 33 | export(new ComputeServiceImpl(), PORT); 34 | } 35 | } 36 | 37 | //服务消费者 38 | static class Customer implements Runnable { 39 | @Override 40 | public void run() { 41 | //使用服务 42 | ComputeService computeService = use(ComputeService.class, HOST, PORT); 43 | for (int i = 0; i < 10; i++) { 44 | int sum = computeService.sum(1, 1); 45 | System.out.println("SUM:" + sum); 46 | try { 47 | TimeUnit.SECONDS.sleep(1); 48 | } catch (InterruptedException e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | } 53 | } 54 | 55 | public static void main(String[] args) { 56 | new Thread(new Provider()).start(); 57 | new Thread(new Customer()).start(); 58 | new Thread(new Customer()).start(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /socket/src/main/java/rpc/SimpleRpcFramework.java: -------------------------------------------------------------------------------- 1 | package rpc; 2 | 3 | import java.io.ObjectInputStream; 4 | import java.io.ObjectOutputStream; 5 | import java.lang.reflect.Method; 6 | import java.lang.reflect.Proxy; 7 | import java.net.ServerSocket; 8 | import java.net.Socket; 9 | 10 | /** 11 | * Created by 李恒名 on 2017/8/17. 12 | */ 13 | public class SimpleRpcFramework { 14 | 15 | /** 16 | * 暴漏服务 17 | * @param serviceImpl 服务的实现 18 | * @param port 服务所处的端口号 19 | */ 20 | public static void export(Object serviceImpl, int port) { 21 | try { 22 | try (ServerSocket server = new ServerSocket(port)) { 23 | while (!Thread.currentThread().isInterrupted()) { 24 | Socket socket = server.accept(); 25 | new Thread(() -> { 26 | try (ObjectInputStream in = new ObjectInputStream(socket.getInputStream())) { 27 | Method method = serviceImpl.getClass().getMethod(in.readUTF(), (Class[]) in.readObject()); 28 | Object result = method.invoke(serviceImpl, (Object[]) in.readObject()); 29 | try (ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream())) { 30 | out.writeObject(result); 31 | } 32 | System.out.println("Invoke method [" + method.getName() + "()] success, form " + socket.getRemoteSocketAddress()); 33 | } catch (Exception e) { 34 | throw new RuntimeException("Export service fail .", e); 35 | } 36 | }).start(); 37 | } 38 | } 39 | } catch (Exception e) { 40 | throw new RuntimeException("Export service fail .", e); 41 | } 42 | System.out.println("Export service " + serviceImpl.getClass().getSimpleName() + " success on port " + port); 43 | } 44 | 45 | /** 46 | * 使用服务 47 | * @param serviceInterface 要使用的服务的接口 48 | * @param host 服务所处的主机名称 49 | * @param port 服务所处的端口号 50 | * @return 服务 51 | */ 52 | public static T use(Class serviceInterface, String host, int port) { 53 | System.out.println(String.format("Use remote service [%s] from [%s:%s]", serviceInterface.getSimpleName(), host, port)); 54 | return (T) Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class[]{serviceInterface}, (proxy, method, args) -> { 55 | try (Socket socket = new Socket(host, port)) { 56 | try (ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream())) { 57 | out.writeUTF(method.getName()); 58 | out.writeObject(method.getParameterTypes()); 59 | out.writeObject(args); 60 | try (ObjectInputStream in = new ObjectInputStream(socket.getInputStream())) { 61 | return in.readObject(); 62 | } 63 | } 64 | } 65 | }); 66 | } 67 | } 68 | --------------------------------------------------------------------------------