单例模式

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

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

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

单例模式练习

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. 关于git的一些零碎知识

    git文件的三个状态:已修改,已暂存,已提交git的三个区域: 工作区,暂存区,对象库 git的几个指针(以master为例) 远程有个master,本地有个master,本地有个指针是指向远程的ma ...

  2. 万字概览 Java 虚拟机

    为什么要学习 JVM 在很多 Java 程序员的开发生涯里,JVM 一直是黑盒子一般的存在,大家只知道运行 Java 程序需要依靠 JVM,千篇一律的配置几个类似 -Xms 和 -Xmx 的参数,可能 ...

  3. node实现文件下载

    1.引入fs const fs = require('fs') const path = reqire('path') 2.方法 const downloadFile = function (dest ...

  4. 解决github下载速度慢问题

    众所周知,GitHub是一个巨大的开源宝库,以及程序员和编程爱好者的聚集地,包括我之前推荐的诸多优秀的开源项目全部都是位于GitHub上.但是每当我们看到优秀的开源项目,准备去 下(bai)载(pia ...

  5. Head First 设计模式 —— 07. 适配器模式

    思考题 你能想到真实世界中,还有哪些适配器的例子? P236 HDMI 转 VGA 转换器 Type-C 转 3.5mm 线 适配器模式解析 客户使用适配器的过程: P241 客户通过目标接口调用适配 ...

  6. CSS_rules

    CSS 特性 1)控制灵活,功能强大 元素-->标签 针对html的元素 2)可以设置html元素的属性,与html框架的进行分离 3)执行效率更高 CSS语法 text-indent 文字缩进 ...

  7. SparkSQL学习进度9-SQL实战案例

    Spark SQL  基本操作 将下列 JSON 格式数据复制到 Linux 系统中,并保存命名为 employee.json. { "id":1 , "name&quo ...

  8. Windows下如何玩转火热的go-zero

    作者:阿啄debugIT 前言 go-zero 是一个集成了各种工程实践的 web 和 rpc 框架.通过弹性设计保障了大并发服务端的稳定性,经受了充分的实战检验. go-zero 包含极简的 API ...

  9. 剑指Offer-连续子数组中的最大和

    题目 输入一个整型数组,数组里有正数也有负数.数组中的一个或连续多个整数组成一个子数组.求所有子数组的和的最大值.要求时间复杂度为 O(n). 输入 [1,-2,3,10,-4,7,2,-5] 返回值 ...

  10. linux硬盘分区和fdisk命令

    分区的几个概念 硬盘分区有三种,主分区.扩展分区.逻辑分区.一个硬盘主分区至少有1个,最多4个,扩展分区可以没有,最多1个.且主分区+扩展分区总共不能超过4个.逻辑分区可以有若干个.在windows下 ...