单例模式

  • 单例模式是一种常用的软件设计模式。

  • 在它的核心结构中只包含一个被成为单例类的特殊类。通过单例模式可以保证系统中一个类职业一个实例而且该实例易于外界访问,从而方面对实例个数的控制并节约系统资源。

  • 如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

单例模式练习

public class Person {

    private int id;
//单例模式:整个系统共享一个对象
public Person(int id) {
super();
this.id = id;
}
//测试
public static void main(String[] args) {
Person p1 = new Person(1);
Person p2 = new Person(2);
}
public void test(){
Singleton ton = Singleton.getInstance();
System.out.println(ton.hashCode());
}
}

单例模式的分类

懒汉式

  • 优点:只有调用方法才创建对象,调用之前不会占用内存

  • 缺点:在多线程模式下不安全

懒汉式相关练习:

public class Singleton {
//私有化构造,只有在本类之中才可以new出来。超出本类无法访问
private Singleton(){
}
//全局对象
private static Singleton singleton=null;
//synchronized 如果加上关键字,则一样
// synchronized 如果没有该关键字,则创建了两个线程不同步
//synchronized 它的位置决定了锁的范围
public static synchronized Singleton getInstance(){
//判断全局对象是否为空
if(singleton==null){
try {
//休眠一秒钟
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//如果为空,就创建该类对象
singleton=new Singleton();
}
//如果不为空,就直接返回该对象
return singleton;
}
public static void main(String[] args) {
//多线程操作
//2.直接使用Thread操作
Thread thread = new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
Singleton ton = Singleton.getInstance();
System.out.println(ton.hashCode());
}
};
thread.start();
Thread thread2 = new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
Singleton ton2 = Singleton.getInstance();
System.out.println(ton2.hashCode());
}
};
//开启新线程
thread2.start();
// Person p = new Person(0);
// p.test();
// Singleton s = new Singleton();
// System.out.println(s.hashCode());
}
}

饿汉式

  • 跟懒汉式的区别,直接创建对象。

  • 饿汉式不管有没有调用getInstance方法,都会预先在系统中创建一个静态对象

  • 懒汉式不会预先创建对象,只有在第一次调用时才创建对象。

  • 优点:在多线程模式下是安全的

  • 缺点:没有调用方法前就加载,会占用系统内存。

饿汉式相关练习:

public class Singleton2 {
//跟懒汉式的区别,直接创建对象
private static Singleton2 ton = new Singleton2();
//私有构造
private Singleton2(){
System.out.println("对象创建成功!");
}
public static Singleton2 getInstance(){
return ton;
}
/**
* 饿汉式不管有没有调用getInstance方法,
* 都会预先在系统中创建一个静态对象。
* 懒汉式不会预先创建对象,只有在第一次调用时,
* 才创建对象。
* 饿汉式
* 优点:在多线程模式下是安全的。
* 缺点:没有调用方法前就加载,会占用系统内存。
* @param args
*/
public static void main(String[] args) { Singleton2 ton = Singleton2.getInstance();
System.out.println(ton.hashCode());
} }

线程安全

  • 饿汉式本身就是线程安全的,可以直接用于多线程而不会出现问题的。

  • 懒汉式是非线程安全的,解决方式如下:

关键字:synchronized:可以用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这个段代码。

使用双重检测机制实现线程安全的懒汉式

使用静态内部类实现线程安全的单例模式


多线程

public class Ch01 {
/**
* 系统默认情况下只运行主线程
* @param args
*
public static void main(String[] args) {
//主线程中开启两个子线程
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
thread1.start();
thread2.start();
}
}
/**
* 多线程类1
* @author alery
*
*/
class Thread1 extends Thread{
/**
* 线程运行期间执行的代码
*/
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("线程1开始运行。。。。。");
//休眠1秒钟
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程1 继续执行......");
}
} /**
* 多线程类2
*/
class Thread2 extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("线程2开始运行。。。。。");
//休眠1秒钟
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程2 继续执行......");
}
}

多线程的三种方式

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask; /**
* JAVA三种方式实现多线程
* @author Administrator
*
*/
public class ThreadTest implements Runnable,Callable<String>{ public static void main(String[] args) throws InterruptedException, ExecutionException {
// TODO Auto-generated method stub
//主线程打印
// System.out.println("线程编号:"+Thread.currentThread().getId());
// new ThreadA().start();
// Thread thread=new Thread(){
// public void run() {
// System.out.println(Thread.currentThread().getId()+"线程正在运行");
// }
// };
// thread.start();
ThreadTest t=new ThreadTest();
// new Thread(t).start();
// new Thread(new Runnable() {
//
// @Override
// public void run() {
// // TODO Auto-generated method stub
// System.out.println(Thread.currentThread().getId()+"线程正在运行");
// }
// }).start();
//Runnable
// FutureTask<String> task=new FutureTask<String>(t);
// new Thread(task).start();
// //获取call方法返回的内容
// System.out.println(task.get());
//线程池内线程最大数量
int threadMaxCount=10;
//线程池
ExecutorService service=Executors.newFixedThreadPool(threadMaxCount);
//定义一个集合存储runnable
List<Future<String>> list=new ArrayList<Future<String>>();
//开始运行10个线程(这10个多线程是由线程池管理的)
for(int i=0;i<threadMaxCount;i++) {
FutureTask<String> task=new FutureTask<String>(t);
//submit把runnable提交给了线程池
Future<String> f=(Future<String>) service.submit(task);
list.add(task);
} // service.shutdown(); for(int i=0;i<list.size();i++) {
Future<String> f=list.get(i);
System.out.println(f.get());
}
} /**
* 2.实现Runnable接口
* 必须重写run方法
* 创建Thread对象,把runnable传递到构造中
* (匿名实现类)
*/
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getId()+"线程正在运行");
} /**
* 3.实现Callable接口
* 重写call方法
* 使用FutureTask类来实现Runnable
* (FutureTask是Runnable的实现类)
* 创建Thread对象,把FutureTask当作Runnable调用了构造参数
* call方法的返回值可以通过FutureTask.get方法得到
* (get方法必须在线程运行之后才可以调用)
* 线程池配合使用比较好
*/
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
String str=Thread.currentThread().getId()+"线程正在运行";
// System.out.println(str);
return str;
} }
/**
* 1.继承Thread类
* 重写run方法
* (匿名类方式实现)
* @author Administrator
*
*/
class ThreadA extends Thread{ /**
* 当线程start时,会执行run
*/
@Override
public void run() {
// super.run();
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getId()+"线程正在运行");
} }

Java——单例模式、多线程的更多相关文章

  1. 【深入】java 单例模式(转)

    [深入]java 单例模式 关于单例模式的文章,其实网上早就已经泛滥了.但一个小小的单例,里面却是有着许多的变化.网上的文章大多也是提到了其中的一个或几个点,很少有比较全面且脉络清晰的文章,于是,我便 ...

  2. 深入Java单例模式(转)

    深入Java单例模式 源自 http://devbean.blog.51cto.com/448512/203501 在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容 ...

  3. Java基础-多线程-②多线程安全问题

    什么是线程的安全问题? 上一篇 Java基础-多线程-①线程的创建和启动 我们说使用实现Runnable接口的方式来创建线程,可以实现多个线程共享资源: class Dog implements Ru ...

  4. Java 单例模式的七种写法

    Java 单例模式的七种写法 第一种(懒汉,线程不安全) public class Singleton { private static Singleton instance; private Sin ...

  5. java单例模式之懒汉式分析

    转自:http://blog.csdn.net/withiter/article/details/8140338 今天中午闲着没事,就随便写点关于Java单例模式的.其实单例模式实现有很多方法,这里我 ...

  6. Java 单例模式探讨

    以下是我再次研究单例(Java 单例模式缺点)时在网上收集的资料,相信你们看完就对单例完全掌握了 Java单例模式应该是看起来以及用起来简单的一种设计模式,但是就实现方式以及原理来说,也并不浅显哦. ...

  7. 单例模式:Java单例模式的几种写法及它们的优缺点

    总结下Java单例模式的几种写法: 1. 饿汉式 public class Singleton { private static Singleton instance = new Singleton( ...

  8. 9种Java单例模式详解(推荐)

    单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象.  懒汉式(线程不安全) 其主要表现在单例类在外 ...

  9. 你真的理解了java单例模式吗?讲别人都忽略的细节!

    前言:老刘这篇文章敢做保证,java的单例模式讲的比大多数的技术博客都要好,讲述别人技术博客都没有的细节!!! 1 java单例模式 直接讲实现单例模式的两种方法:懒汉式和饿汉式,单例模式的概念自己上 ...

随机推荐

  1. Redis 设计与实现 6:五大数据类型之列表

    列表对象有 3 种编码:ziplist.linkedlist.quicklist. ziplist 和 linkedlist 是 3.2 版本之前的编码. quicklist 是 3.2 版本新增的编 ...

  2. stm32之can总线过滤器研究

    stm32的can总线的配置如下:       CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式      CAN_InitStructure.CAN_A ...

  3. 耗子大叔弹窗来自百度搜索引擎导流的弹窗JS源码赏析

    刚看到https://coolshell.cn/articles/9308.html 耗子大叔评价梁斌站点被百度封杀事件言论  然后在自己个人网站酷壳网站上发布了一段JS代码  当请求来自百度导流过来 ...

  4. 基于http的netty demo

    1.引入netty的pom <dependency> <groupId>io.netty</groupId> <artifactId>netty-all ...

  5. RabbitMQ不讲武德,发个消息也这么多花招

    前言 本篇博客已被收录GitHub:https://zhouwenxing.github.io/ 文中所涉及的源码也已被收录GitHub:https://github.com/zhouwenxing/ ...

  6. FFT原理及C++与MATLAB混合编程详细介绍

    一:FFT原理 1.1 DFT计算 在一个周期内的离散傅里叶级数(DFS)变换定义为离散傅里叶变换(DFT). \[\begin{cases} X(k) = \sum_{n=0}^{N-1}x(n)W ...

  7. 一文讲尽门面日志slf4j和log4j、log4j2、logback依赖jar引用关系

    公众号Mac代码分割阅读链接 前言 之前都是使用SparkStreaming开发,最近打算学习一下Flink,就从官网下载了Flink 1.11,打算搞一个客户端,将程序提交在yarn上.因为Flin ...

  8. Docker环境下升级PostgreSQL

    查阅PostgreSQL官方文档可以得知,官方提供了两种方式对数据库进行升级--pg_dumpall与pg_upgrade. pg_dumpall是将数据库转储成一个脚本文件,然后在新版数据库中可以直 ...

  9. for _ in range( ):

    for _ in range( ): { //函数体 } 其中"-"只是一个占位符,可以把它理解为i或者j等等任意的字母. 上面代码相当于同下: for i in range( ) ...

  10. 最新最简洁Spring Cloud Oauth2.0 Jwt 的Security方式

    因为Spring Cloud 2020.0.0和Spring Boot2.4.1版本升级比较大,所以把我接入过程中的一些需要注意的地方告诉大家 我使用的版本是Spring boot 2.4.1+Spr ...