从线程更新java对象的属性?
变量var的值始终为0。这几乎就像从未调用过该方法一样。我希望能够从线程内部更改val的值,如果调用getVal(),我希望能够访问新值从线程更新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(
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();
}
}
}