Browse Source

feat: 👍 单例模式

master
niushuai233 1 year ago
parent
commit
746661c9ec
  1. 66
      src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/CASSingleton.java
  2. 33
      src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/EnumSingleton.java
  3. 48
      src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/Singleton.java
  4. 70
      src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/lazy/LazySingleton.java
  5. 64
      src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/lazy/LazySingletonInnerClass.java
  6. 24
      src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/package-info.java
  7. 108
      src/test/java/cc/niushuai/demo/designpattern/creatormodel/singleton/SingletonTest.java

66
src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/CASSingleton.java

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
/*
* Copyright (C) 2023 niushuai233 niushuai.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cc.niushuai.demo.designpattern.creatormodel.singleton;
import cn.hutool.core.thread.ThreadUtil;
import java.util.concurrent.atomic.AtomicReference;
/**
* TODO
*
* @author niushuai233
* @date 2024/1/5 11:49
* @since 0.0.1
*/
public class CASSingleton {
private static final AtomicReference<CASSingleton> INSTANCE = new AtomicReference<>();
private CASSingleton() {
ThreadUtil.sleep(3000);
System.out.println(Thread.currentThread().getName() + " -> " + getClass().getName() + " has been initialized");
}
public static CASSingleton getInstance() {
CASSingleton casSingleton = INSTANCE.get();
if (casSingleton != null) {
return casSingleton;
}
INSTANCE.compareAndSet(null, new CASSingleton());
return INSTANCE.get();
}
public static CASSingleton getInstance_forEach() {
while (true) {
CASSingleton casSingleton = INSTANCE.get();
if (casSingleton != null) {
return casSingleton;
}
if (INSTANCE.compareAndSet(null, new CASSingleton())) {
return INSTANCE.get();
}
}
}
public void hello(String world) {
System.out.println("hello " + world);
}
}

33
src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/EnumSingleton.java

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
/*
* Copyright (C) 2023 niushuai233 niushuai.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cc.niushuai.demo.designpattern.creatormodel.singleton;
/**
* 枚举单例模式
*
* @author niushuai233
* @date 2024/1/5 14:00
* @since 0.0.1
*/
public enum EnumSingleton {
INSTANCE;
public void hello(String item) {
System.out.println("Hello " + item);
}
}

48
src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/Singleton.java

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
/*
* Copyright (C) 2023 niushuai233 niushuai.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cc.niushuai.demo.designpattern.creatormodel.singleton;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 简单单例模式
*
* @author niushuai233
* @date 2024/1/5 11:17
* @since 0.0.1
*/
public class Singleton {
public static final Map<String, Object> map = new ConcurrentHashMap<>();
private Singleton() {
System.out.println(Thread.currentThread().getName() + " -> " + getClass().getName() + " has been initialized");
}
/**
* 简单单例模式
*
* @return
* @author niushuai233
* @date 2024/1/5 11:18
* @since 0.0.1
*/
public static Map<String, Object> getMap() {
return map;
}
}

70
src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/lazy/LazySingleton.java

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
/*
* Copyright (C) 2023 niushuai233 niushuai.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cc.niushuai.demo.designpattern.creatormodel.singleton.lazy;
import cn.hutool.core.date.DateUtil;
/**
* 懒汉模式
*
* @author niushuai233
* @date 2024/1/5 11:14
* @since 0.0.1
*/
public class LazySingleton {
private static LazySingleton INSTANCE;
private LazySingleton() {
System.out.println(Thread.currentThread().getName() + " -> " + getClass().getName() + " has been initialized");
}
/**
* 获取LazySingleton 线程不安全 存在同时获取多个实例时new了多个instance到内存中
*
* @return
* @author niushuai233
* @date 2024/1/5 11:15
* @since 0.0.1
*/
public static LazySingleton getInstance_threadUnsafe() {
if (null == INSTANCE) {
INSTANCE = new LazySingleton();
}
return INSTANCE;
}
/**
* 获取LazySingleton 线程安全
*
* @return
* @author niushuai233
* @date 2024/1/5 11:16
* @since 0.0.1
*/
public static synchronized LazySingleton getInstance_threadSafe() {
if (null == INSTANCE) {
INSTANCE = new LazySingleton();
}
return INSTANCE;
}
public void hello(String str) {
System.out.println(Thread.currentThread().getName() + ": hello " + str + " ==>" + DateUtil.now());
}
}

64
src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/lazy/LazySingletonInnerClass.java

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
/*
* Copyright (C) 2023 niushuai233 niushuai.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cc.niushuai.demo.designpattern.creatormodel.singleton.lazy;
import cn.hutool.core.date.DateUtil;
/**
* 使用内部类的方式进行懒加载 自身线程安全 不需要锁来管控线程安全
*
* @author niushuai233
* @date 2024/1/5 11:21
* @since 0.0.1
*/
public class LazySingletonInnerClass {
public static LazySingletonInnerClass INSTANCE = new LazySingletonInnerClass();
private LazySingletonInnerClass() {
System.out.println(Thread.currentThread().getName() + " -> " + getClass().getName() + " has been initialized");
}
public static void say() {
INSTANCE.hello("say");
}
/**
* 自身线程安全 不需要锁 只有加载内部类时单例才会被实例化
*
* @return
* @author niushuai233
* @date 2024/1/5 11:23
* @since 0.0.1
*/
public static LazySingletonInnerClass getInstance() {
return LazySingletonInnerClassHolder.INSTANCE;
}
public void hello(String str) {
System.out.println(Thread.currentThread().getName() + ": hello " + str + " ==>" + DateUtil.now());
}
public static class LazySingletonInnerClassHolder {
private LazySingletonInnerClassHolder() {
System.out.println(Thread.currentThread().getName() + " -> " + getClass().getName() + " has been initialized");
}
public static final LazySingletonInnerClass INSTANCE = new LazySingletonInnerClass();
}
}

24
src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/package-info.java

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
/*
* Copyright (C) 2023 niushuai233 niushuai.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* 单例模式
*
* @author niushuai233
* @date 2024/1/5 11:09
* @since 0.0.1
*/
package cc.niushuai.demo.designpattern.creatormodel.singleton;

108
src/test/java/cc/niushuai/demo/designpattern/creatormodel/singleton/SingletonTest.java

@ -0,0 +1,108 @@ @@ -0,0 +1,108 @@
/*
* Copyright (C) 2023 niushuai233 niushuai.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cc.niushuai.demo.designpattern.creatormodel.singleton;
import cc.niushuai.demo.designpattern.creatormodel.singleton.lazy.LazySingleton;
import cc.niushuai.demo.designpattern.creatormodel.singleton.lazy.LazySingletonInnerClass;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
/**
* 单例模式 test
*
* @author niushuai233
* @date 2024/1/5 14:05
* @since 0.0.1
*/
public class SingletonTest {
@Test
public void testSingleton() {
Singleton.map.put("date", DateUtil.now());
System.out.println(Singleton.map.get("date"));
}
@Test
public void testSingleton_lazy_unsafe() {
List<String> strings = List.of("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12");
new ForkJoinPool().submit(() -> strings.parallelStream().forEach(item -> LazySingleton.getInstance_threadUnsafe().hello(item)));
ThreadUtil.sleep(3000);
System.out.println("testSingleton_lazy_unsafe end");
}
@Test
public void testSingleton_lazy_safe() {
List<String> strings = List.of("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12");
new ForkJoinPool().submit(() -> strings.parallelStream().forEach(item -> LazySingleton.getInstance_threadSafe().hello(item)));
ThreadUtil.sleep(3000);
System.out.println("testSingleton_lazy_unsafe end");
}
@Test
public void testSingletonInnerClass() {
LazySingletonInnerClass.say();
System.out.println("============================================================================================");
List<String> strings = List.of("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12");
new ForkJoinPool().submit(() -> strings.parallelStream().forEach(item -> LazySingletonInnerClass.getInstance().hello(item)));
ThreadUtil.sleep(3000);
System.out.println("testSingletonInnerClass end");
}
/**
* 仍然有可能创建出多个对象但是INSTANCE一旦被赋予 则不再被改变 其他已创建的对象可认同为无用对象 并且等待被GC回收
*
* @return
* @author niushuai233
* @date 2024/1/5 14:54
* @since 0.0.1
*/
@Test
public void testCASSingleton() {
List<String> strings = List.of("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12");
new ForkJoinPool().submit(() -> strings.parallelStream().forEach(item -> CASSingleton.getInstance().hello(item)));
CASSingleton.getInstance().hello("world");
ThreadUtil.sleep(3000);
System.out.println("testSingletonInnerClass end");
}
@Test
public void testEnumSingleton() {
List<String> strings = List.of("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12");
new ForkJoinPool().submit(() -> strings.parallelStream().forEach(item -> EnumSingleton.INSTANCE.hello(item)));
EnumSingleton.INSTANCE.hello("world");
ThreadUtil.sleep(3000);
System.out.println("testEnumSingleton end");
}
}
Loading…
Cancel
Save