我的测试程序要求输入一个字符串并每隔2秒打印一次。我已经读过一些关于java内存模型或者线程如何不立即更新主内存中的变量。
我已尝试使用volatile
和static
属性。同步修改变量line
的代码块。变量更改后的wait()/notifi()
和其他变量。如何指定line
作为参考而不是作为值?我使用的方法我试错了吗?为什么对象在作为监视器时可以保持完美同步但是当它们作为指针时它们不能成为什么?
public class TestSharedVariable {
static String line= "";
public static void main(String[] args) {
// For reading from keyboard
Scanner keyboard = new Scanner(System.in);
Printer p = new Printer(line);
p.start();
// Reads a line from keyboard into the shared variable
while(!line.equals("quit")){
line = keyboard.nextLine();
}
}
}
class Printer extends Thread{
private volatile String line;
public Printer(String palabra){
this.line = palabra;
}
/* Prints the line each 2 sec */
@Override
public void run(){
while(!line.equals("quit")){
try {
sleep(2000);
} catch (InterruptedException e) {e.printStackTrace();}
System.out.println(this.getName() + ": " + line);
}
}
}
输出:
Thread-0:
asdf
Thread-0:
Thread-0:
答案 0 :(得分:3)
您有两个主要问题:
换句话说,即使您最初将Printer对象的行变量设置为与TestSharedVariable的静态行变量相同的引用,稍后更改TestSharedVariable的静态行变量的引用也不会影响Printer行变量的引用赋值。这与线程无关,而与理解引用变量有关。想想C或其他类似语言中的指针等引用变量。如果两个变量指向同一个对象,则将一个变量更改为指向另一个对象将不会影响第一个变量。
要使代码生效,两个变量必须共享对同一个可变对象的引用,并且必须更改可变对象的状态,而不是引用它
例如,
import java.util.Scanner;
public class TestSharedVariable {
static volatile MutableObject mutableObject = new MutableObject();
public static void main(String[] args) {
// For reading from keyboard
Scanner keyboard = new Scanner(System.in);
Printer p = new Printer(mutableObject);
new Thread(p, "Print thread").start();
// Reads a line from keyboard into the shared variable
while (!mutableObject.getData().equals("quit")) {
mutableObject.setData(keyboard.nextLine());
}
}
}
class Printer implements Runnable {
private volatile MutableObject mutableObject;
public Printer(MutableObject mutableObject) {
this.mutableObject = mutableObject;
}
/* Prints the line each 2 sec */
@Override
public void run() {
while (!mutableObject.getData().equals("quit")) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + ": " + mutableObject);
}
}
}
class MutableObject {
private String data = "";
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
@Override
public String toString() {
return data;
}
}