精华内容
下载资源
问答
  • 什么时候/为什么我的Java单例实例被销毁
    2021-02-12 22:32:10

    我有一个设置为启动Java活动(称为MyJavaActivity)的android应用,这反过来又会启动NativeActivity。NativeActivity完成后,它将返回到MyJavaActivity。

    我还有一个Java单例类(称为MyJavaSingleton),我希望在应用程序的整个生命周期中都将其保留在内存中。我从NativeActivity(使用JNI)中设置了一些单例类的成员变量,以后可以由MyJavaActivity检索。

    问题是,MyJavaSingleton实例似乎一直在内存中,直到NativeActive退出为止,但是当MyJavaActivity再次启动时,似乎又以某种方式再次设置为null,因此我在NativeActivity中设置的所有变量现在都重置为其默认值。为什么会这样?

    public class MyJavaActivity extends Activity implements View.OnTouchListener

    {

    @Override

    public void onCreate(Bundle savedInstanceState)

    {

    super.onCreate(savedInstanceState);

    MyJavaSingleton.Instance().DoStuff();

    }

    @Override

    public boolean onTouch(View arg0, MotionEvent arg1)

    {

    Intent intent = new Intent(MyJavaActivity.this, NativeActivity.class);

    startActivity(intent); // at this point, android_main will be executed

    }

    }

    /

    public class MyJavaSingleton

    {

    static private MyJavaSingleton mInstance = null;

    synchronized public static MyJavaSingleton Instance()

    {

    if( mInstance == null )

    {

    mInstance = new MyJavaSingleton();

    Log.v(TAG, "New MyJavaSIngleton instance");

    }

    return mInstance;

    }

    }

    /

    // Native

    void android_main(struct android_app* state)

    {

    // Do various stuff, set some variables on the MyJavaSingleton

    // At this point, MyJavaSingleton.mInstance is still at the same address in memory, which is good //

    ANativeActivity_finish(state->activity);

    exit(0);

    // Problem: sometime after this exit and before MyJavaActivity::onCreate is called, MyJavaSingleton.mInstance is set to null!

    }

    在上面的代码提取中,在首次启动应用程序时打印“ New

    MyJavaSIngleton实例”,然后在NativeActivity退出后(即,在android_main退出之后)再次打印,并再次调用MyJavaActivity的onCreate。

    重新输入MyJavaActivity时,为什么MyJavaSingleton.mInstance变为NULL?

    更多相关内容
  • 单例即单个实例,在我们生产活动中有些类没必要好多实例存在的。单例模式严格来讲有8种写法。利用类加载器帮助我们实现单例模式。用jvm来保证我们的线程安全。public class Mgr01{private static final Mgr01 ...

    单例即单个实例,在我们生产活动中有些类没必要好多实例存在的。

    单例模式严格来讲有8种写法。

    利用类加载器帮助我们实现单例模式。用jvm来保证我们的线程安全。

    public class Mgr01{

    private static final Mgr01 INSTANCE=new Mgr01();

    private Mgr01();

    Public static Mgr01 getInstance{return INSTANCE};

    Public static void main(String[]args){

    Mgr01 m1=Mgr01.getInstance();

    Mgr01 m2=Mgr01.getInstance();

    System.out.println(m1==m2);

    }

    唯一缺点,无论是否用到,都会有一个实例。

    第一个稍微改造版,给第一个没什么区别。

    public class Mgr02{

    private static final Mgr02 INSTANCE;

    Static{

    INSTANCE=new Mgr01();

    private Mgr02();

    Public static Mgr02 getInstance{return INSTANCE};

    Mgr02 m1=Mgr02.getInstance();

    Mgr02 m2=Mgr02.getInstance();

    懒汉式:达到初始化目的,带来了线程安全问题

    public class Mgr03{

    private static final Mgr03 INSTANCE;

    private Mgr03();

    Public static Mgr03 getInstance(){

    If(INSTANCE==null){

    try{Thread.sleep(1);}catch(Exception e){}

    Instance=new Mgr03();

    Return Instance;

    };

    for(int i=0;i<1000;i++){

    New Thread(()->{

    System.out.println(Mgr03 .getInstance.hashCode());

    }).start();

    懒汉式进行改进

    public class Mgr04{

    private static final Mgr04 INSTANCE;

    private Mgr04();

    Public static synchronized Mgr04 getInstance(){

    Instance=new Mgr04();

    System.out.println(Mgr04 .getInstance.hashCode());

    缺点:这样效率会降低,那有没有办法加锁的同时,效率也提高了。不在整个方法加锁。

    public class Mgr05{

    private static final Mgr05 INSTANCE;

    private Mgr05();

    Public static Mgr05 getInstance(){

    Synchronized(Mgr05 .class){

    Instance=new Mgr05();}

    System.out.println(Mgr05 .getInstance.hashCode());

    在多线程访问下,不能做到只有一个实例。不能保证判断Instance为空的时候进来两个线程。

    双重校验锁:

    public class Mgr06{

    private static final Mgr06 INSTANCE;

    INSTANCE=new Mgr06();

    private Mgr06();

    Public static Mgr06 getInstance(){

    Synchronized(Mgr06 .class){

    Instance=new Mgr06();}

    System.out.println(Mgr06 .getInstance.hashCode());

    静态内部类,jvm保证单实例,加载外部类不会加载内部类,这样可以实现懒加载.

    public class Mgr07{

    Private Static class Mgr07Holder{

    private static final Mgr07 INSTANCE=new Mgr07 ();

    private Mgr07();

    Public static Mgr07 getInstance(){

    Return Mgr07Holder.Instance;

    System.out.println(Mgr07 .getInstance.hashCode());

    以上可以通过反射创建。

    枚举模式创建单例,

    public class EnumSingleton {

    private EnumSingleton(){}

    public static EnumSingleton getInstance(){

    return Singleton.INSTANCE.getInstance();

    }

    private static enum Singleton{

    INSTANCE;

    private EnumSingleton singleton;

    //JVM会保证此方法绝对只调用一次

    private Singleton(){

    singleton = new EnumSingleton();

    }

    public EnumSingleton getInstance(){

    return singleton;

    单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如:

    1.需要频繁实例化然后销毁的对象。

    2.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。

    3.有状态的工具类对象。

    4.频繁访问数据库或文件的对象。

    以下都是单例模式的经典使用场景:

    1.资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。

    2.控制资源的情况下,方便资源之间的互相通信。如线程池等。

    应用场景举例:

    1.外部资源:每台计算机有若干个打印机,但只能有一个PrinterSpooler,以避免两个打印作业同时输出到打印机。内部资源:大多数软件都有一个(或多个)属性文件存放系统配置,这样的系统应该有一个对象管理这些属性文件

    2. Windows的Task Manager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗? 不信你自己试试看哦~

    3. windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。

    4. 网站的计数器,一般也是采用单例模式实现,否则难以同步。

    5. 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。

    6. Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。

    7. 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。

    8. 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。

    9. 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。

    10. HttpApplication 也是单位例的典型应用。熟悉ASP.Net(IIS)的整个请求生命周期的人应该知道HttpApplication也是单例模式,所有的HttpModule都共享一个HttpApplication实例。

    89012083869e06b2f0852086bac148e3.png

    在spring中

    spring的Bean默认的是单例的,Bean的作用域可以通过Bean标签的scope属性进行设置,Bean的作用域包括:

    默认情况下scope="singleton",那么该Bean是单例,任何人获取该Bean实例的都为同一个实例;

    scope="prototype",任何一个实例都是新的实例;

    scope="request",在WEB应用程序中,每一个实例的作用域都为request范围;

    scope="session",在WEB应用程序中,每一个实例的作用域都为session范围;

    注意:在默认情况下,Bean实例在被Spring容器初始化的时候,就会被实例化,默认调用无参数的构造方法。在其它情况下,Bean将会在获取实例的时候才会被实例化。

    在使用log4j框架时也注意到了其使用的是单例,当然也为了保证单个线程对日志文件的读写时不出问题,与使用spring管理bean的目标不是相似,如下为其logfactory单例创建的源码。

    展开全文
  • 本篇文章主要介绍了JAVA创建和销毁对象的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 类的创建与销毁(一)

    2021-03-22 13:46:18
    优雅的创建实例通过构造函数创建实例...}Demo(int var1, int var2){//implement logic}}优点:简单的实现了多个实例化入口,可以通过级联调用缺点:实例返回的对象无法子类化、无法单例化等,灵活性差多实例参数时并...

    优雅的创建实例

    通过构造函数创建实例

    通过多参数构造函数重载,提供多个实例化入口

    class Demo {

    Demo(){

    this(0, 0);

    }

    Demo(int var){

    this(var, 0);

    }

    Demo(int var1, int var2){

    //implement logic

    }

    }

    优点:

    简单的实现了多个实例化入口,可以通过级联调用

    缺点:

    实例返回的对象无法子类化、无法单例化等,灵活性差

    多实例参数时并且这些参数不确定需要时,需要提供大量构造重载入口,繁琐

    通过静态工厂方法创建实例

    通过静态方法提供多内容的实例化

    class Demo {

    private Demo() {}

    public static Demo getInstance() {

    return new Demo();

    }

    }

    优点:

    可以根据不同的实例用途进行方法命名,提高调用者的对不同实例入口的认知

    可以根据业务需求和当前状态的选择是返回一个新的实例还是一个已缓存的类实例

    返回类型可以是返回的具体实例的超类,该超类可以是一个协议接口,从而实现了返回值的子类化

    缺点:

    当工厂方法不在需要实例化的类中时,需要被实例化的类无法做到子类化

    多实例参数并且这些参数不确定需要时,需要提供大量静态方法,繁琐

    通过传入JavaBean创建实例

    通过打包多个参数到一个JavaBean对象,来减少方法签名数

    class DataBean {

    int var1;

    int var2;

    int var3;

    }

    class Demo {

    Demo(DataBean data){}

    }

    优点:

    多参数的构造中,可以减少参数的传递,减少调用者的负担

    缺点:

    传入JavaBean的方式是先传入JavaBean,再获取实例,而该JavaBean的内容是可变的,这给实例带来了不确定性。

    通过Builder构建器创建实例

    通过创建Builder构建器,从而创建对象

    class Demo {

    private int var1;

    private String var2;

    Demo(Builder builder) {

    this.var1 = builder.var1;

    this.var2 = builder.var2;

    }

    static class Builder {

    private int var1;

    private String var2;

    public Builder setVar1(int var){

    this.var1 = var;

    return this;

    }

    public Builder setVar2(String var) {

    this.var2 = var;

    return this;

    }

    public build(){

    //1. check the fileds in builder

    return new Demo(this);

    }

    }

    }

    优点:

    相比多个构造器,Builder模式可以实现多参数的自由组合,也有利于后期多参数扩展,可维护性更好

    相比JavaBean,传入的参数是当前对象可控可检查的,入参非法则不允许创建对象,更加安全

    链式调用,更符合函数式编程实现,对每个参数有强约束,更加易于阅读和操作

    缺点:

    多构造器模式更加冗长,适用于大于4个参数的情况

    对性能开销有一定的负面影响

    最优的单例实现方式

    枚举单例和Atomic原子引用

    //枚举法

    public class EnumSingleton{

    private EnumSingleton(){}

    public static EnumSingleton getInstance(){

    return Singleton.INSTANCE.getInstance();

    }

    private static enum Singleton{

    INSTANCE;

    private EnumSingleton singleton;

    //JVM会保证此方法绝对只调用一次

    private Singleton(){

    singleton = new EnumSingleton();

    }

    public EnumSingleton getInstance(){

    return singleton;

    }

    }

    }

    //原子操作 + 自旋锁(乐观锁)

    public class AtomicSingleton {

    private static AtomicReference INSTANCE = new AtomicReference<>();

    private AtomicSingleton() {}

    public static AtomicSingleton getInstace(){

    while (true) {

    AtomicSingleton current = INSTANCE.get();

    if(current != null){ return current; }

    current = new AtomicSingleton();

    if(INSTANCE.compareAndSet(null, current)) { return current; }

    }

    }

    }

    优点:

    多线程安全

    枚举:延迟加载,原子操作:乐观锁,保证了性能的最优化

    绝对的序列化安全和反射攻击安全

    不可实例化类的声明

    class Demo {

    // 私有化缺省构造,让调用者无法实例化

    private Demo(){

    //若有反射攻击,抛出一个异常

    throw new AssertionError();

    }

    }

    避免创建不必要的对象

    //code 1

    String s1 = new String("str");

    //code 2

    String s2 = "str";

    code 1中,“str”已经为一个创建的实例,通过String的构造器再创建一个对象,这是一个无意义的操作

    code2中,s2指向的不是一个String对象,而是常量池中的一个String地址,若“str”在常量池中已经存在相同字面值的一份,则引用直接指向它,否则才创建,这个做法类似于基本类型的创建机制

    public static void main(String[] args) {

    Integer sum = 0;

    for (int i = 0; i <= Integer.MAX_VALUE; i++) {

    sum += i;

    }

    System.out.println(sum);

    }

    上述代码中,由于装箱的存在,创建了

    math?formula=2%5E%7B31%7D个Integer对象,大大浪费了性能,所以尽量使用基础类型,避免无意识的装箱操作

    但不是说尽量避免创建对象,首先要保证业务的通畅和代码的可维护性、可阅读性。不要为了减少对象的创建,来做一些额外的操作(如维护对象池),若维护的对象是轻量级,这个操作反而降低了效率,并且增加了代码的复杂度。而对足够重量级的对象(如JDBC)进行这种操作才能带来收益

    展开全文
  • Java单例模式(4)

    2021-03-22 13:46:03
    本文介绍Java单例模式第四种这种策略的模式是使用Java的关键字synchronized修饰了getInstance()方法,用的是同步方法。这在操作系统中被认为是管程。管程的实质不是由操作系统进行了特殊操作,而是由编译器进行了...

    本文介绍Java单例模式第四种

    这种策略的模式是使用Java的关键字synchronized修饰了getInstance()方法,用的是同步方法。这在操作系统中被认为是管程。管程的实质不是由操作系统进行了特殊操作,而是由编译器进行了同步代码块的封装,类似于C语言中的pthread_mutex_lock和pthread_mutex_unlock,而在操作系统层面,实际上就是一对原子操作,也被成为原语,意思就是对于共享资源的加锁。只有使用完了这个资源才会释放这个资源,由其他进程使用。

    synchronized 修饰的方法或者代码块。此处是加了全局锁,其实锁定的是Student04.class ,每次执行getInstance方法都要判断是否获取到了锁对象, 因此是可以保证获取的实例是同一个,但是其他线程在运行到这个方法的时候,因为获取不到锁对象,因此会不断的尝试去获取锁对象,直到获取到为止,因此会有效率上面的影响。

    代码部分

    package singleton;

    public class Student04 {

    public static Student04 instance;

    private Student04(){

    }

    public synchronized static Student04 getInstance() {

    if (instance == null) {

    try {

    Thread.sleep(1);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    instance = new Student04();

    }

    return instance;

    }

    public static void main(String[] args) {

    for (int i = 0; i < 100; i++) {

    new Thread(new Runnable() {

    @Override

    public void run() {

    System.out.println(Student04.getInstance().hashCode());

    }

    }).start();

    }

    }

    }

    运行代码输出:

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    4661163

    展开全文
  • ## 单例模式是最简单也是最基础的设计模式之一,下边一起学习一下单例模式! 一.单例模式的定义: 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志...
  • JAVA单例模式

    2021-02-12 18:32:20
    定义:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。类型:创建类模式类图:类图知识点:1....单例模式应该是23种设计模式中最简单的一种模式了。它有以下几个要素:• 私有的...
  • 其实所谓的单例模式并不是他的对象永远就只有一个,一个类的对象在我们需要的时候可以随时创建,但是我们不需要管实例的销毁,因为垃圾管理器会自动销毁,这也是java语言的一个特点之一;但是单例模式就是在该类在...
  • 首先我们介绍一下单例模式 单例类是只有一个实例对象; 该单例对象必须由单例类自行创建; 单例类对外提供一个访问该单例的全局访问点。 单例模式的优点 ... 某类需要频繁实例化,而创建的对象又频繁被销毁
  • 8道常考Java单例模式面试题

    千次阅读 2021-02-12 22:40:05
    Java单例设计模式是GoF23种设计模式之一,也是是使用频率最高的设计模式之一,所以想参加java程序员岗位面试的朋友们,必须要提前学习好java单例模式面试题的内容,java单例模式在初级中高级的面试中几乎都会出现,...
  • Java单例模式8种方式 详解

    千次阅读 热门讨论 2021-01-31 19:19:03
    所谓单例,指的就是单实例,有且仅有一个类实例,这个单例不应该由人来控制,而应该由代码来限制,强制单例。 运用场景很多,例如网站的在线人数,window系统的任务管理器,网站计数器等等,这些都是单例模式的运用...
  • 文章目录1. 单例模式的定义2. 单例模式的设计要素3. 单例模式的6种实现及各实现...这样做的好处是:有些实例,全局只需要一个就够了,使用单例模式就可以避免一个全局使用的类,频繁的创建与销毁,耗费系统资源。 2. 单
  • 单例模式: 单例模式(Singleton)是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个...
  • Java单例模式

    2021-02-26 09:33:32
    再孬再好,就你一个单例模式单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的...
  • strtok函数实际上是要把第一个参数的字符串进行修改的。因为这个原因这个字符串的存储... 说明1)单例模式:确保一个类只有一个实例,自行实例化并向系统提供这个实例2)单例模式分类:饿单例模式(类加载时实例化一个...
  • Java单例实现方式 经典:懒汉式、饿汉式、双重检测锁 关键: 私有化构造方法 通过方法去获取单例对象 懒汉(调用时再去初始化)、饿汉(直接初始化) Demo: //饿汉式 public class Demo1 { private static Demo...
  • 1)单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能2)当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用...
  • 单例模式有 3 个特点: 1、单例类只有一个实例对象; 2、该单例对象必须由单例类自行创建; 3、单例类对外提供一个访问该单例的全局访问点; 单例模式的两种实现形式: 第 1 种:懒汉式单例,可理解为懒加载模式,...
  • 1.单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象...
  • 什么是单例模式 简述 单例模式(Singleton Pattern)是创建型设计模式中最简单且应用最为广泛的设计模式之一,单例模式属于创建型模式,提供了一种对象创建的思路。 使用单例模式时,目标类被要求确保有且仅有一个...
  • 1)单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能2)当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用 ...
  • 为了他人的利益,我将在下面介绍我从调查中收集到的内容:只要原型bean本身不持有对另一个资源(如数据库连接或会话对象)的引用,只要删除了对该对象的所有引用或对象超出范围,就...因为后处理器本身是单例范围的,所以...
  • java单例模式

    万次阅读 多人点赞 2018-05-25 14:59:26
     本文首先概述了单例模式产生动机,揭示了单例模式的本质和应用场景。紧接着,我们给出了单例模式在单线程环境下的两种经典实现:饿汉式和懒汉式,但是饿汉式是线程安全的,而懒汉式是非线程安全的。在多线程环境下...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 51,567
精华内容 20,626
关键字:

java 单例 销毁

java 订阅