该提交包括以下主要变更:
1. 新增了`SingletonPattern.java`,实现了购物车管理器的单例模式,用于记录商品添加到购物车的信息,并在购买结束后打印出商品清单。这是针对设计模式专题之单例模式的练习。 2. 新增了`LeetCode138.java`,实现了复制一个包含随机指针的链表。这是对链表操作和复制的练习。 3. 新增了`Proxy.java`,实现了动态代理,用于扣费20作为中介费的案例。这是对Java代理模式的实践。 4. 对`TestCacheThreadPool.java`进行了修改,添加了多个线程安全的示例代码,包括单例模式的实现、ConcurrentHashMap的使用、ReentrantLock和Condition的使用等。这是对多线程和并发编程的探索。 这次提交的代码涵盖了设计模式、链表操作、动态代理和并发编程等多个方面,展示了作者在编程领域的广泛兴趣和实践能力。
This commit is contained in:
parent
3aaee55251
commit
cd4c443077
@ -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<String, Integer> carHas = null;
|
||||
|
||||
public ManagerCar() {
|
||||
this.carHas = new HashMap<>();
|
||||
}
|
||||
|
||||
public HashMap<String, Integer> 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<String, Integer> 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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
53
src/main/java/cn/whaifree/test/Proxy.java
Normal file
53
src/main/java/cn/whaifree/test/Proxy.java
Normal file
@ -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
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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<String, String> 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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user