Java并发编程:发布与逸出

238 阅读2分钟

src=http___i0.hdslb.com_bfs_article_807aa46619617caf3a3ea976300b575abae0676c.png&refer=http___i0.hdslb.webp 本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

       上文(《Java并发编程:线程安全性》)给大家介绍了多线程的优缺点,以及线程安全的概念及实现方式,而本片文章将给大家介绍的是发布与逸出,错误的发布与逸出将会引发线程安全性问题。

发布

       将线程的对象放在公共域,使其他线程可见,即为发布。
       发布的方式主要有三种:
       1. 将要发布的对象使用public修饰,这样其它类即可看见。代码如下:

public class Test {
	public List<String> userNames = new ArrayList<>();
}

       2. 通过公共方法将私有变量的引用返回,代码如下:

public class Test {
	private List<String> userNames = new ArrayList<>();
        
        public List<String> getUserNames(){
            return userNames;
        }
}

       上述代码中,列表userNames虽然是私有变量,但是getUserNames方法将其引用发布出去后,其它类也可访问。
       3. 匿名内部类方式。

public class Test {        
        public void start(){
            Thread thread = new Thread(new Runable(){
                
                @Override
                public void run(){
                    System.out.println("do some things...");
                }
            });
            thread.start();
        }
}

       上述代码中,使用new Runable创建了一个匿名内部类,在此过程中,Test类隐式地向Runable发布了一个this对象,在匿名内部类中可Test类对象。

逸出

       错误的发布,即为逸出。

public class Test {   
        private Thread thread;
        public Test(){
            thread = new Thread(new Runable(){
                
                @Override
                public void run(){
                    System.out.println("do some things...");
                }
            });
        }
}

       上述代码中,在Test类的构造器中进行匿名内部类创建,在这过程中,Java要把Test类的当前对象传给Runable,但是由于这是在构造器中,对象还未创建成功,因此就会出现错误的发布。

安全的发布方式

  • 将对象放在静态域中。对象会在初次使用Test类的时候进行初始化。
public class Test {
	public static Object obj = new Object();
}
  • 将对象放在final域中。
  • 使用volatile修饰或者使用AtomicReference
  • 使用锁
  • 事实不可变对象。即对象没有用final修饰,但是在使用过程中,对象不会被修改。

后言

       既然看到这里了,感觉有所收获的朋友,不妨来个大大的点赞吧~~~