面试中被问到了老生常谈的单例模式,之前看得比较浅,只觉得单例模式保证对象的全局唯一性,那么这个“全局唯一性”针对一个App的全局,还是一个Activity呢?
直接写了一个demo来测试:两个activity,一个单例类:
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Singleton singleton = Singleton.getInstance();
Log.i("single","in main, singleton: "+singleton.toString());
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
new Thread(new Runnable() {
@Override
public void run() {
Singleton anotherSingleton = Singleton.getInstance();
Log.i("single","in main new thread, singleton: "+anotherSingleton.toString());
}
}).start();
}
});
}
}
SecondActivity.java
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Singleton singleton = Singleton.getInstance();
Log.i("single","in second, singleton: "+singleton.toString());
}
}
Log中的输出结果
09-14 13:34:51.909 21088-21088/com.example.fireflies.testapplication I/single: in main, singleton: com.example.fireflies.testapplication.Singleton@1eb0de7
09-14 13:35:12.549 21088-21262/com.example.fireflies.testapplication I/single: in main new thread, singleton: com.example.fireflies.testapplication.Singleton@1eb0de7
09-14 13:35:12.604 21088-21088/com.example.fireflies.testapplication I/single: in second, singleton: com.example.fireflies.testapplication.Singleton@1eb0de7
运行后发现,两个Activity中的singleton对象都是同一个。
结论:单例模式中的全局唯一对应的是整个APP,比如你在一个activity中已经创建了单例类的实例,在没有被回收的境况下,在另一个activity中去get这个实例,还是同一个对象,也即单例的全局唯一性。
至于MainActivity中为何button点击会另外创建一个线程,是因为MainActivity和SecondActivity虽是两个Activity类,但他们仍然运行在同一个线程中,即UI线程,之前一直以为两个类应该是两个线程,其实不是。因此在MainActivity中再去创建一个线程,同时访问singleton对象,发现仍然是同一个,更能证明单例的范围是整个App,即使是多线程环境。