线程安全第三大类问题——对象发布和初始化的安全问题
什么是发布
- 什么是发布:将对象可以超过这个类范围之外可以使用;比如对象声明为public,或者方法的return是一个对象,或者将类作为参数传到其他类的方法中,这些都能称之为发布。
什么是逸出
- 什么是逸出:发布到了不该发布的地方就叫逸出。
- 方法返回一个private对象(private本意是不让外部访问)
- 还未完成初始化(构造函数没完全执行完毕)就把对象提供给外界。比如:
- 在构造函数中未初始化完毕就this赋值
- 隐式逸出——注册监听事件
- 构造函数中运行线程
对于逸出的第一条,可以返回副本。
* 代码演示
在构造函数中未初始化完毕就this赋值
package controller;
/**
* 在构造函数中未初始化完毕就this赋值
*/
public class MultiThradsError4 {
static Point point;
public static void main(String[] args) throws InterruptedException {
new PointMaker().start();
//两种执行结果不同,可以自己执行一下
// Thread.sleep(10);
Thread.sleep(105);
if(point != null){
System.out.println(point);
}
}
}
class Point{
private final int x,y;
public Point(int x, int y) throws InterruptedException {
this.x = x;
MultiThradsError4.point = this;
Thread.sleep(100);
this.y = y;
}
@Override
public String toString() {
return "Point{" +
"x=" + x +
", y=" + y +
'}';
}
}
class PointMaker extends Thread{
@Override
public void run(){
try {
new Point(1,1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
隐式逸出——注册监听事件(使用观察者模式)
package controller;
import java.awt.*;
import java.util.EventListener;
/**
* 隐式逸出——注册监听事件(使用观察者模式)
*/
public class MultiThreadError5 {
int cout;
public MultiThreadError5(MySource source) {
//注册监听器
source.registerListener(new EventListener() {
@Override
public void onEvent(Event e) {
System.out.println("\n我得到的数字"+cout);
}
});
for (int i =0; i<10000;i++){
System.out.print(i);
}
cout = 100;
}
public static void main(String[] args) {
MySource mySource = new MySource();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
mySource.eventCome(new Event() {
});
}
}).start();
MultiThreadError5 multiThreadError5 = new MultiThreadError5(mySource);
}
static class MySource{
private EventListener listener;
void registerListener(EventListener eventListener){
this.listener = eventListener;
}
void eventCome(Event e){
if(listener != null){
listener.onEvent(e);
}else{
System.out.println("还未初始化完毕");
}
}
}
interface EventListener{
void onEvent(Event e);
}
interface Event{
}
}
构造函数中新建线程
package controller;
import java.util.HashMap;
import java.util.Map;
/**
* 构造函数中新建线程
*/
public class MultiThreadError6 {
private Map<String,String> states;
public MultiThreadError6() {
new Thread(new Runnable() {
@Override
public void run() {
states = new HashMap<>();
states.put("1","周一");
states.put("2","周二");
states.put("3","周三");
states.put("4","周四");
}
}).start();
}
public Map<String,String> getStates(){
return states;
}
public static void main(String[] args) throws InterruptedException {
MultiThreadError6 multiThreadError6 = new MultiThreadError6();
//延迟一下结果不同
// Thread.sleep(1000);
System.out.println(multiThreadError6.states.get("1"));
}
}