单例模式

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

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

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

单例模式练习

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. 数据库分库分表容量划分建议参考阿里云DRDS原则

    做分库分表的时候 一直想知道分库分表容量的最优规则有什么好的建议,以下是参考阿里云 DRDS 分库分表的规则,还是有一定的参考意义 .

  2. Spring Boot 自动配置之@Conditional的使用

    Spring Boot自动配置的"魔法"是如何实现的? 转自-https://sylvanassun.github.io/2018/01/08/2018-01-08-spring_ ...

  3. WPF APP 启动时增加特殊逻辑

    public partial class App : Application { public App() { this.Startup += (o1, e1)=>{ string comman ...

  4. 基于LDAP&&Role-based Authorization Strategy实现Jenkins团队权限管理

    在实际工作中,存在多个团队都需要Jenkins来实现持续交付,但是又希望不同团队之间进行隔离,每个项目有自己的view, 只能看到自己项目的jenkins job. 但是,jenkins默认的权限管理 ...

  5. 对于k8s微服务的性能测试监控平台搭建

    之前有写过对于传统项目的性能测试监控,但是对于目前市场占比已经很低,大部分项目使用k8s,今天讲一下对于k8s如何去监控. 对于k8s的监控我们所有的操作都要在master下进行. 一.部署grafa ...

  6. 白日梦的Elasticsearch笔记(一)基础篇

    目录 一.导读 1.1.认识ES 1.2.安装.启动ES.Kibana.IK分词器 二.核心概念 2.1.Near Realtime (NRT) 2.2.Cluster 2.3.Node 2.4.In ...

  7. LeetCode374 猜数字大小

    我们正在玩一个猜数字游戏. 游戏规则如下:我从 1 到 n 选择一个数字. 你需要猜我选择了哪个数字.每次你猜错了,我会告诉你这个数字是大了还是小了.你调用一个预先定义好的接口 guess(int n ...

  8. k8s之ServiceAccount

    导读 上一篇说了k8s的RBAC授权模式,今天就来简单看一下其中涉及到的ServiceAccount. 简介 k8s创建两套独立的账号系统,原因如下: (1)User账号给用户用,Service Ac ...

  9. linux之平均负载(学习笔记非原创)

    什么是平均负载 [root@111 ~]# uptime 11:03:33 up 149 days, 17:34, 1 user, load average: 0.08, 0.05, 0.01 最后三 ...

  10. leetcode 864. 获取所有钥匙的最短路径(BFS,状态压缩)

    题目链接 864. 获取所有钥匙的最短路径 题意 给定起点,要求在最短步骤内收集完所有钥匙,遇到每把锁之前只有 有对应的钥匙才能够打开 思路 BFS+状态压缩典型题目 先确定起点和总的钥匙数目,其次难 ...