From cd4c44307708153f3758956f76b09f085f94b5b9 Mon Sep 17 00:00:00 2001 From: kyriewhluo Date: Wed, 14 Aug 2024 20:00:18 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=A5=E6=8F=90=E4=BA=A4=E5=8C=85=E6=8B=AC?= =?UTF-8?q?=E4=BB=A5=E4=B8=8B=E4=B8=BB=E8=A6=81=E5=8F=98=E6=9B=B4=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增了`SingletonPattern.java`,实现了购物车管理器的单例模式,用于记录商品添加到购物车的信息,并在购买结束后打印出商品清单。这是针对设计模式专题之单例模式的练习。 2. 新增了`LeetCode138.java`,实现了复制一个包含随机指针的链表。这是对链表操作和复制的练习。 3. 新增了`Proxy.java`,实现了动态代理,用于扣费20作为中介费的案例。这是对Java代理模式的实践。 4. 对`TestCacheThreadPool.java`进行了修改,添加了多个线程安全的示例代码,包括单例模式的实现、ConcurrentHashMap的使用、ReentrantLock和Condition的使用等。这是对多线程和并发编程的探索。 这次提交的代码涵盖了设计模式、链表操作、动态代理和并发编程等多个方面,展示了作者在编程领域的广泛兴趣和实践能力。 --- .../designPattern/SingletonPattern.java | 93 +++++++ .../leetCode/LinkedList/LeetCode138.java | 86 +++++++ src/main/java/cn/whaifree/test/Proxy.java | 53 ++++ .../cn/whaifree/test/TestCacheThreadPool.java | 235 +++++++++++++++++- 4 files changed, 463 insertions(+), 4 deletions(-) create mode 100644 src/main/java/cn/whaifree/designPattern/SingletonPattern.java create mode 100644 src/main/java/cn/whaifree/leetCode/LinkedList/LeetCode138.java create mode 100644 src/main/java/cn/whaifree/test/Proxy.java diff --git a/src/main/java/cn/whaifree/designPattern/SingletonPattern.java b/src/main/java/cn/whaifree/designPattern/SingletonPattern.java new file mode 100644 index 0000000..22bf363 --- /dev/null +++ b/src/main/java/cn/whaifree/designPattern/SingletonPattern.java @@ -0,0 +1,93 @@ +package cn.whaifree.designPattern; + +import java.util.HashMap; +import java.util.Scanner; +import java.util.function.BiConsumer; + +public class SingletonPattern { + + /** + * https://kamacoder.com/problempage.php?pid=1074 + * + * 【设计模式专题之单例模式】1.小明的购物车 + * 题目描述 + * 小明去了一家大型商场,拿到了一个购物车,并开始购物。请你设计一个购物车管理器,记录商品添加到购物车的信息(商品名称和购买数量),并在购买结束后打印出商品清单。(在整个购物过程中,小明只有一个购物车实例存在)。 + * 输入描述 + * 输入包含若干行,每行包含两部分信息,分别是商品名称和购买数量。商品名称和购买数量之间用空格隔开。 + * 输出描述 + * 输出包含小明购物车中的所有商品及其购买数量。每行输出一种商品的信息,格式为 "商品名称 购买数量"。 + * 输入示例 + * Apple 3 + * Banana 2 + * Orange 5 + * 输出示例 + * Apple 3 + * Banana 2 + * Orange 5 + * 提示信息 + * 本道题目请使用单例设计模式: + * + * 使用私有静态变量来保存购物车实例。 + * + * 使用私有构造函数防止外部直接实例化。 + */ + + static class ManagerCar{ + + private HashMap carHas = null; + + public ManagerCar() { + this.carHas = new HashMap<>(); + } + + public HashMap getCarHas() { + return carHas; + } + + private volatile static ManagerCar managerCar; + + public static ManagerCar getManagerCar() { + if (managerCar == null) { + synchronized (ManagerCar.class) { + if (managerCar == null) { + managerCar = new ManagerCar(); + } + } + } + return managerCar; + } + + } + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + HashMap carHas = ManagerCar.getManagerCar().getCarHas(); + + + while (true) { + String nextLine = scanner.nextLine(); + if ("stop".equals(nextLine)) { + break; + } + String[] s = nextLine.split(" "); + String obj = s[0]; + Integer num = Integer.valueOf(s[1]); + carHas.put(obj, carHas.getOrDefault(obj, 0) + num); + /** + * 添加商品到购物车 + * public void addItem(String name, int quantity) { + * items.merge(name, quantity, Integer::sum); + * + */ + } + + carHas.forEach( + (s, integer) -> System.out.println(s + " " + integer) + ); + + scanner.close(); + + } + + +} diff --git a/src/main/java/cn/whaifree/leetCode/LinkedList/LeetCode138.java b/src/main/java/cn/whaifree/leetCode/LinkedList/LeetCode138.java new file mode 100644 index 0000000..21dd4ce --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/LinkedList/LeetCode138.java @@ -0,0 +1,86 @@ +package cn.whaifree.leetCode.LinkedList; + +import org.junit.Test; + +public class LeetCode138 { + + static class Node { + int val; + Node next; + Node random; + + public Node(int val) { + this.val = val; + this.next = null; + this.random = null; + } + } + + @Test + public void test() { + + // 1 2 3 + // 1 3 + // 2 1 + +// Node node1 = new Node(1); +// Node node2 = new Node(2); +// Node node3 = new Node(3); +// node1.next = node2; +// node2.next = node3; +// node1.random = node3; +// node2.random = node1; +// Node node = copyRandomList(node1); +// System.out.println(node); + + +// [[7,null],[13,0],[11,4],[10,2],[1,0]] + Node node1 = new Node(7); + Node node2 = new Node(13); + Node node3 = new Node(11); + Node node4 = new Node(10); + Node node5 = new Node(1); + node1.next = node2; + node2.next = node3; + node3.next = node4; + node4.next = node5; + node2.random = node1; + node3.random = node5; + node4.random = node3; + node5.random = node1; + Node node = copyRandomList(node1); + System.out.println(node); + } + + public Node copyRandomList(Node head) { + Node index = head; + while (index != null) { + Node tmp = index.next; + index.next = new Node(index.val); + index.next.next = tmp; + index = index.next.next; + } + + index = head; + while (index != null) { + if (index.random != null) { + index.next.random = index.random.next; + } + index = index.next.next; + } + + + Node newHead = head.next; + index = newHead; + Node tmpPreIndex = head; + while (index.next != null) { + tmpPreIndex.next = tmpPreIndex.next.next; + tmpPreIndex = tmpPreIndex.next; + index.next = index.next.next; + index = index.next; + } + tmpPreIndex.next = null; + return newHead; + } + +} diff --git a/src/main/java/cn/whaifree/test/Proxy.java b/src/main/java/cn/whaifree/test/Proxy.java new file mode 100644 index 0000000..9bf4c86 --- /dev/null +++ b/src/main/java/cn/whaifree/test/Proxy.java @@ -0,0 +1,53 @@ +package cn.whaifree.test; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import java.lang.reflect.Method; + +public class Proxy { + + public static void main(String[] args) { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(Rent.class); + enhancer.setCallback(new Agency()); + Rent o = (Rent) enhancer.create(); + System.out.println("起始的钱:" + o.money); + o.rent(); + System.out.println("剩下的钱:" + o.money); + } + + static class Rent{ + int money = 100; + + void rent() { + System.out.println("租房!"); + } + } + + static class Agency implements MethodInterceptor { + @Override + public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { + Rent o1 = (Rent) o; + o1.money -= 20; + System.out.println("扣费20为中介费"); + return methodProxy.invokeSuper(o, objects); + //https://blog.csdn.net/z69183787/article/details/106878203 + /** + * 调用invoke实际是调用cglib生成的子类的方法 + * 这个子类 + * method{ + * interceptor(obj.method) + * } + * 正确使用: + * 将obj从其他地方传进来 + * + * + * 调用invokeSuper实际是调用父类的方法method + */ + } + + } + +} diff --git a/src/main/java/cn/whaifree/test/TestCacheThreadPool.java b/src/main/java/cn/whaifree/test/TestCacheThreadPool.java index 1ad3399..f272958 100644 --- a/src/main/java/cn/whaifree/test/TestCacheThreadPool.java +++ b/src/main/java/cn/whaifree/test/TestCacheThreadPool.java @@ -1,11 +1,15 @@ package cn.whaifree.test; +import org.junit.Test; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.Charset; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; public class TestCacheThreadPool { @@ -25,6 +29,17 @@ public class TestCacheThreadPool { System.out.println("\n"); } + ConcurrentHashMap map = new ConcurrentHashMap<>(); + map.put("1", "233"); + String compute = map.compute("1", (k, v) -> { + return k + v; + }); + String merge = map.merge("1", "233", (k, v) -> { + return k + v; // 没有就value,有就+value + }); + System.out.println(merge); + System.out.println(compute); + // ExecutorService executorService = Executors.newCachedThreadPool(); // for (int i = 0; i < 10; i++) { // int finalI = i; @@ -45,4 +60,216 @@ public class TestCacheThreadPool { } -} + @Test + public void single() { + for (int i = 0; i < 100; i++) { + new Thread(new Runnable() { + @Override + public void run() { + System.out.println(Thread.currentThread().getName() + " " + Single.getSingle()); + } + }).start(); + } + } + + static class Single { + private static Single o = null; + + public static Single getSingle() { + if (o == null) { + synchronized (Single.class) { + if (o == null) { // 防止第二个线程再创建一个 + System.out.println("创建"); + o = new Single(); + } + } + } + return o; + } + } + + + static class Singleton { + // 不使用volatile关键字 + private static Singleton instance; + + private Singleton() { + } + + public static Singleton getInstance() { + if (instance == null) { + synchronized (Singleton.class) { + if (instance == null) { + instance = new Singleton(); + } + } + } + return instance; + } + + public static void main(String[] args) { + // 创建多个线程尝试获取单例实例 + for (int i = 0; i < 10; i++) { + new Thread(() -> { + for (int j = 0; j < 10; j++) { + new Thread(new Runnable() { + @Override + public void run() { + System.out.println(Thread.currentThread().getName() + " 获取到的实例为: " + Singleton.getInstance()); + } + }).start(); + } + System.out.println("-======"); + }).start(); + } + } + } + + + + + static class MultiConditionDemo { + private final ReentrantLock lock = new ReentrantLock(); + private final Condition condition1 = lock.newCondition(); + private final Condition condition2 = lock.newCondition(); + private String message = "等待消息"; + + public static void main(String[] args) { + MultiConditionDemo demo = new MultiConditionDemo(); + new Thread(() -> demo.producer()).start(); + new Thread(() -> demo.consumer()).start(); + } + + public void producer() { + lock.lock(); + try { + while ("等待消息".equals(message)) { + condition1.await(); // 等待条件1 + } + message = "这是生产者发送的消息"; + System.out.println("生产者发送消息:" + message); + condition2.signal(); // 通知条件2上的等待线程 + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + lock.unlock(); + } + } + + public void consumer() { + lock.lock(); + try { + while (!"这是生产者发送的消息".equals(message)) { + condition2.await(); // 等待条件2 + } + System.out.println("消费者接收到的消息:" + message); + message = "等待消息"; + condition1.signal(); // 通知条件1上的等待线程 + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + lock.unlock(); + } + } + } + + static class reentrantLockDemo { + static ReentrantLock lock = new ReentrantLock(); + static int num = 0; + static Condition condition = lock.newCondition(); + + public static void main(String[] args) { + new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 100; i++) { + lock.lock(); + + while (num % 2 == 0) { + try { + condition.await(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + System.out.println("A"); + num++; + condition.signalAll(); + lock.unlock(); + } + } + }).start(); + new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 100; i++) { + lock.lock(); + while (num % 2 != 0) { + try { + condition.await(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + System.out.println("B"); + num++; + condition.signalAll(); + lock.unlock(); + + } + } + }).start(); + + } + } + + static class synDemo { + static Object lock = new Object(); +// static Condition condition = lock.newCondition(); + static int num = 0; + public static void main(String[] args) throws InterruptedException { + new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 100; i++) { + synchronized (lock) { + while (num % 2 == 0) { + try { + lock.wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + System.out.println("A"); + num++; + lock.notify(); + } + } + } + }).start(); + + new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 100; i++) { + synchronized (lock) { + while (num % 2 == 1) { + try { + lock.wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + System.out.println("B"); + num++; + lock.notify(); + } + } + } + }).start(); + + } + + } + +} \ No newline at end of file