我有一个Java类,可以启动2个独立的线程。第一个线程启动正常,所有变量都正确。
当我启动第二个线程时,来自线程1的全局变量将更改为线程2中设置的值。
我尝试添加全局变量更新的同步块,但这不起作用。
有没有办法解决这个问题?我希望每个线程都启动并使用自己的值而不会干扰其他线程值。
编辑:
我的Thread类的片段:
public abstract class ConsumerIF implements Runnable {
public static Element root = null;
public static String name = null;
public static String type = null;
public static String location = null;
public final synchronized void reconfigure() throws FatalDistributionException {
Document doc = builder.build(new StringReader(xmlCollector));
root = doc.getRootElement();
Element nameElement = root.getChild("name");
Element typeElement = root.getChild("type");
Element locationElement = root.getChild("location");
Element scheduleElement = root.getChild("schedule");
if (nameElement != null && typeElement != null && locationElement != null){
name = nameElement.getTextTrim();
type = typeElement.getTextTrim();
location = locationElement.getTextTrim();
}
}
}
答案 0 :(得分:13)
静态变量在所有线程之间共享,这就是它们的静态变量。如果要使用不同的值,请使用ThreadLocals或(更好),在不同的线程中使用具有非静态变量的不同对象。如果没有进一步的代码,很难说更多。
答案 1 :(得分:6)
同步仅控制线程对共享状态的访问。
如果你想要每个线程单独的状态,那么你需要为每个线程声明该信息的不同实例(例如类)。例如只需在每个Thread
的{{1}}方法中实例化一个新对象,或执行相关结构的副本(例如集合的深层副本)
另一种方法是调查ThreadLocal,其中每个主题将拥有指定资源的不同副本。
答案 2 :(得分:2)
如果您不希望共享变量,则不要使用全局变量(您可能在Java中使用static
)。在线程启动时初始化新对象,创建一个新字段。例如:
public class HelloThread extends Thread {
private MyObject myThreadVariable; // This is the thread-local variable
public void run() {
myThreadVariable = new MyObject(); // initialization when the thread starts
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new HelloThread()).start();
(new HelloThread()).start();
}
}
如果您确实需要在不同代码段的本地访问您的对象,请使用ThreadLocal
public class UniqueThreadIdGenerator {
private static final AtomicInteger uniqueId = new AtomicInteger(0);
// Value obtained from uniqueNum.get() will be thread-local even though uniqueNum is static
private static final ThreadLocal <Integer> uniqueNum = new ThreadLocal <Integer> () {
@Override protected Integer initialValue() {
return uniqueId.getAndIncrement();
}
};
public static int getCurrentThreadId() {
return uniqueNum.get();
}
}
同步的作用是防止两个线程同时进入同步的代码块。它也与在线程之间共享变量有关,但在相反的情况下 - 当你想要它们共享时。如果没有同步,您对一个线程的更改可能会或可能不会被其他线程看到(请参阅here和here)
答案 3 :(得分:0)
如果我理解正确,您应该查看final
修饰符:
private final String s;
这确保无法修改s
,因此您的线程将无法更改其值。
还要确保您的线程不会尝试修改它们不应该修改的值,而是复制它们。
答案 4 :(得分:0)
如果要使用静态变量,则应在同步方法中的类对象上使用synchronized块。
public abstract class ConsumerIF implements Runnable {
public static Element root = null;
public static String name = null;
public static String type = null;
public static String location = null;
public final synchronized void reconfigure() throws FatalDistributionException {
synchrnized(ConsumerIF.class) {
Document doc = builder.build(new StringReader(xmlCollector));
root = doc.getRootElement();
Element nameElement = root.getChild("name");
Element typeElement = root.getChild("type");
Element locationElement = root.getChild("location");
Element scheduleElement = root.getChild("schedule");
if (nameElement != null && typeElement != null && locationElement != null){
name = nameElement.getTextTrim();
type = typeElement.getTextTrim();
location = locationElement.getTextTrim();
}
}
}
}
确保从class object
上的同步方法/块访问所有静态变量,而不是在实例变量或this
实例上访问。您使用的synchronized方法适用于this
实例意味着您调用方法的当前对象和所有对象共享静态变量。