从线程更新java对象的属性?

从线程更新java对象的属性?,java,Java,变量var的值始终为0。这几乎就像从未调用过该方法一样。我希望能够从线程内部更改val的值,如果调用getVal(),我希望能够访问新值 public class Test1 { private int val; public Test1() { val=0; } public void changeVal() { new Thread(new Runnable() { public void run(

变量var的值始终为0。这几乎就像从未调用过该方法一样。我希望能够从线程内部更改val的值,如果调用getVal(),我希望能够访问新值

public class Test1 {
    private int val;

    public Test1() {
        val=0;
    }

    public void changeVal() {

        new Thread(new Runnable() {
            public void run() {
                val=1;
            }
        }).start();
    }

    public int getVal() {
        return this.val;
    }

    public static void main(String[]args) {
        Test1 x=new Test1();
        x.changeVal();
        System.out.println("VAl: "+x.getVal() );
    }
}

您已在声明之间设置了竞争条件

  x.changeVal();

尝试将以下代码放在上述两个语句之间

    try {
        Thread.sleep(100);
    }
    catch (Exception e) {
        System.out.println("Exception: " + e);
    }

这使您的新线程有机会在到达println语句之前建立。

该值已更改,但是(大多数情况下)在方法“run”中的var=1之前执行getVal()。执行顺序由线程调度程序控制,但正如Johnny Mopp所说,添加.join()将解决此问题

  public void changeVal() throws InterruptedException {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                val = 1;

            }

        });
        t.start();
        t.join();

    }

    public static void main(String[] args) throws InterruptedException {
        Test1 x = new Test1();
        x.changeVal();

        System.out.println("VAl: " + x.getVal());
    }

您需要更改主要方法,如下所示:

public static void main(String[]args)
 {
    Test1 x=new Test1();
    x.changeVal();
   try {
        Thread.sleep(100);//sometime here 
    }
    catch (Exception e) {
        System.out.println("Exception: " + e);
    }
    System.out.println("VAl: "+x.getVal() );

 }


您可以使用
Thread.join()
changeVal()
方法中将主线程与子线程连接。

一个解决方案可以使用ReentrantLock

将其定义为类成员变量

Lock lock = new ReentrantLock();
在changeVal中使用此锁

public void changeVal() throws InterruptedException {
    if (lock.tryLock()) {
        try {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    val = val + 1;
                }
            }).start();

        } finally {
            lock.unlock();
        }
    }

}

您需要将变量
设置为volatile
,如果希望在main方法中打印变量之前更改变量,则需要安排一些同步或锁定。这使得线程完全没有意义


很难看出它的真正意义。

在打印值之前,可能需要等待线程启动/完成
这几乎就像从未调用过该方法一样,这是一个非常准确的描述,说明了如果代码没有正确同步,跨线程可见性如何会失败。它确实提供了一个机会,但却不能保证。此外,这从本质上否定了对另一个线程的需求,因为您的代码现在实际上是单线程的。同意,不需要使用另一个线程,但让我们把它看作是一个并发操作。
public void changeVal() throws InterruptedException {
    if (lock.tryLock()) {
        try {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    val = val + 1;
                }
            }).start();

        } finally {
            lock.unlock();
        }
    }

}