Java 是否可以在线程中更新属性
假设我创建了一个对象,并在线程中运行它,类似这样Java 是否可以在线程中更新属性,java,multithreading,runnable,Java,Multithreading,Runnable,假设我创建了一个对象,并在线程中运行它,类似这样 public class Main { public static void main(String[] args) { SomeClass p = new SomeClass (143); p.start(); p.updateNumber(144); }} 是否可以使用methode UpdateEnumber()将SomeClass中传递的参数更新为fallows: #更新 结果: 144 144 144 14
public class Main {
public static void main(String[] args) {
SomeClass p = new SomeClass (143);
p.start();
p.updateNumber(144);
}}
是否可以使用methode UpdateEnumber()将SomeClass中传递的参数更新为fallows:
#更新
结果:
144
144
144
144
144
谢谢是的,但是您需要将
数字
声明为,或者()使用a而不是长将数字声明为易失性
什么时候需要
当多个线程使用相同的
变量,每个线程将有其
拥有该服务器的本地缓存的副本
变量所以,当它更新
值,它实际上在
本地缓存不在主变量中
记忆。另一根线是
使用同一个变量并不知道
有关于被更改的值的任何信息吗
这是另一条线。为了避免这种情况
问题是,如果将变量声明为
易失性,则不会存储它
在本地缓存中。每当线程
如果正在更新值,它将被更新
到主存储器。那么,其他线程
可以访问更新的值
SomeClass
即使它是可运行的,它也只是一个普通类,任何引用它的线程都可以访问它的对象。在你的例子中。您没有在任何地方调用updateNumber()
form,但是如果在p.start()之后调用它,则是从实际生成实例的线程访问它。如果您在run()
中调用updateNumber()
,那么您将从刚刚启动的线程访问它
另一个问题是:在设置中从多个线程更改它是否安全?答案是否定的。如果根据当前值更改,则必须将其声明为volatile
(比方说),或者synchronize
。同步的方式和内容取决于您对它的实际操作。是的,您可以调用p.updateNumber(…)
,但您需要注意线程同步问题 当满足以下所有条件时,您可以使用关键字volatile
:
- 对变量的写入不依赖于其当前值,或者您可以确保只有一个线程更新该值
- 该变量不参与其他状态变量的不变量
- 在访问变量时,不需要出于任何其他原因进行锁定
否则,我建议使用某种同步策略
class SomeClass implements Runnable {
private Integer number;
SomeClass (int number) {
this.number = Integer.valueOf(number);
}
@Override
public void run() {
while(true){
System.out.println(getNumber());
}
}
public void updateNumber(int n){
synchronized(number){
number = Integer.valueOf(n);
}
}
public int getNumber(){
synchronized(number){
return number.intValue();
}
}
}
另一个没有提到的选项是使用Doug Lee在Java 1.5中引入的并发包,这是您应该使用的选项,而不是上面提到的同步
使用原子类,这些类可以解决所有并发问题。(在一定程度上)
大概是这样的:
private AtomicInteger number = new AtomicInteger(0);
public void updateNumber(int n) {
number.getAndSet(n);
}
public int getNumber() {
return number.get();
}
在我看来,《实践中的Java并发》是关于Java线程的最好的书
这可能需要同步一个可能同步的方法,或者进程间通信。long
的长度为64位,在32位机器上更新它需要两个(非原子)操作,所以您可能会得到一个混乱的值,其中包含来自不同值的低位和高位。您应该同步
setter方法或使用原子长
。同步在这里是必不可少的。但是,您必须将变量声明为volatile,以确保该值将是最新的oneUpdate:我检查了最新的JLS,并且写入声明为volatile的long
确实是一个原子操作,因此您最初的建议是可以的。。。不需要额外的同步。@Moh,如果只有一个线程(在本例中是主线程)调用updateNumber
,那么使用关键字volatile
就足够了。:)但在结果中,为什么143的值没有出现?它直接从144开始,我甚至在考试前就睡了一觉sysout@Moh,您还需要在读取时进行同步。请使用getNumber()
方法查看我的编辑。在number
上同步不是一个好主意,尤其是在同步的块内重新指定其值时。一个好的替代方法是使用单独的对象,例如objectlock=newobject()。。。已同步(锁定){…}
或仅使方法本身同步
。但实际上,只要使用AtomicInteger
@mattball,我完全同意,我很高兴你发表了这样的评论。我只是想告诉@Moh,数字的读写需要同步,或者至少是原子的。在过去,我发现使用原子数据类型仍然需要根据情况进行同步。。。
private AtomicInteger number = new AtomicInteger(0);
public void updateNumber(int n) {
number.getAndSet(n);
}
public int getNumber() {
return number.get();
}