diff --git a/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/CASSingleton.java b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/CASSingleton.java new file mode 100644 index 0000000..15848ce --- /dev/null +++ b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/CASSingleton.java @@ -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 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); + } +} diff --git a/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/EnumSingleton.java b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/EnumSingleton.java new file mode 100644 index 0000000..641bb08 --- /dev/null +++ b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/EnumSingleton.java @@ -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); + } +} diff --git a/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/Singleton.java b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/Singleton.java new file mode 100644 index 0000000..1993221 --- /dev/null +++ b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/Singleton.java @@ -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 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 getMap() { + return map; + } +} diff --git a/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/lazy/LazySingleton.java b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/lazy/LazySingleton.java new file mode 100644 index 0000000..e6c0b1a --- /dev/null +++ b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/lazy/LazySingleton.java @@ -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()); + } +} diff --git a/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/lazy/LazySingletonInnerClass.java b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/lazy/LazySingletonInnerClass.java new file mode 100644 index 0000000..2b3f42a --- /dev/null +++ b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/lazy/LazySingletonInnerClass.java @@ -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(); + } +} diff --git a/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/package-info.java b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/package-info.java new file mode 100644 index 0000000..f5b45bd --- /dev/null +++ b/src/main/java/cc/niushuai/demo/designpattern/creatormodel/singleton/package-info.java @@ -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; \ No newline at end of file diff --git a/src/test/java/cc/niushuai/demo/designpattern/creatormodel/singleton/SingletonTest.java b/src/test/java/cc/niushuai/demo/designpattern/creatormodel/singleton/SingletonTest.java new file mode 100644 index 0000000..972c879 --- /dev/null +++ b/src/test/java/cc/niushuai/demo/designpattern/creatormodel/singleton/SingletonTest.java @@ -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 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 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 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 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 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"); + } +}