Java new 对象是否是原子性的?

发布于 2022-09-05 02:01:11 字数 281 浏览 22 评论 0

public static void main(Sting args[]){
     Object a=null;
     new Thread(){
              a=new xxx()
     }.start();

     new Thread(){
              a=new xxx()
     }.start();
}

想问,xxx()方法里有复杂的对象初始化逻辑,new关键字创建对象,是原子性的吗?如果不是,会不会就出现了对象初始化错乱的问题?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

但可醉心 2022-09-12 02:01:11

没明白你的意思,如果我猜得不错的话:

这完全取决于你的构造方法里面的具体的逻辑,毕竟代码是人写的。

public class Test {
    static class A{
        public A(){
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd:hh:mm:ss:SS");
                System.out.println(sdf.format(new Date()) + "--begin --从线程" + Thread.currentThread().getName() + "中创建A");
                Thread.sleep(2000);
                System.out.println(sdf.format(new Date()) + "--end--从线程" + Thread.currentThread().getName() + "中创建A");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        new Thread(new Runnable(){

            @Override
            public void run() {
                System.out.println("A is " +new A());
            }
            
        }).start();
        
        new Thread(new Runnable(){

            @Override
            public void run() {
                System.out.println("A is " +new A());
            }
            
        }).start();
    }
}

输出:

2017-06-16:11:46:43:780--begin --从线程Thread-1中创建A
2017-06-16:11:46:43:780--begin --从线程Thread-0中创建A
2017-06-16:11:46:45:786--end--从线程Thread-0中创建A
2017-06-16:11:46:45:786--end--从线程Thread-1中创建A
A is nwe.Test$A@1e6a629c
A is nwe.Test$A@27fcb25d

另一个例子,构造器中包含同步块,每一个线程都需要等待前面的线程执行完成后才能执行。

import java.text.*;
import java.util.Date;

public class Test {
    static class A{
        public A(){
            try {
                synchronized (Test.class) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd:hh:mm:ss:SS");
                    System.out.println(sdf.format(new Date()) + "--begin --从线程" + Thread.currentThread().getName() + "中创建A");
                    Thread.sleep(2000);
                    System.out.println(sdf.format(new Date()) + "--end--从线程" + Thread.currentThread().getName() + "中创建A");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        new Thread(new Runnable(){

            @Override
            public void run() {
                System.out.println("A is " +new A());
            }
            
        }).start();
        
        new Thread(new Runnable(){

            @Override
            public void run() {
                System.out.println("A is " +new A());
            }
            
        }).start();
    }
}

输出:

2017-06-16:11:49:33:548--begin --从线程Thread-0中创建A
2017-06-16:11:49:35:549--end--从线程Thread-0中创建A
A is nwe.Test$A@717c3e10
2017-06-16:11:49:35:550--begin --从线程Thread-1中创建A
2017-06-16:11:49:37:553--end--从线程Thread-1中创建A
A is nwe.Test$A@27280786
睡美人的小仙女 2022-09-12 02:01:11

建议参考线程安全的单例模式

寄意 2022-09-12 02:01:11

不具有,比如构造方法中写了多条逻辑,在执行构造方法时,是可以中断的。

笨死的猪 2022-09-12 02:01:11

“原子性”这种描述太抽象,楼主提问的时候最好不要认为所有人对某个词的认识都完全一样。我只能说构造方法是线程安全的,对于每一个对象,构造方法只会被执行一次,只会被一个线程执行。

荆棘i 2022-09-12 02:01:11

初始化过程是分成几个步骤的,比如:分配空间、初始化对象值、将对象指向空间,最关键的是这几个步骤间还有可能乱序重排,导致部分初始化情况出现(可以参照单例模式的DCL模式),所以为了保证正确初始化,通常对象上要加volatile禁止重排

不念旧人 2022-09-12 02:01:11

不是原子性的。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文