Java multithreading and global variables

I have a Java class that runs 2 separate threads. The first thread starts fine, and all the variables are correct.

When I start the second thread, the global variables from thread 1 change to the values ​​set in thread 2.

I tried to add synchronized blocks where global variables are updated, but this did not work.

Is there any way to solve this problem? I want each thread to start and use its own values ​​without interference in other values ​​of the stream.

EDIT:

A snippet of my Thread class:

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(); } } } 
+7
source share
5 answers

Static variables are distributed among all threads, which makes them static. If you want to use different values, use ThreadLocals or (much better) use different objects with non-static variables in differrent threads. Without further code, it's hard to say more though.

+13
source

Synchronization simply controls the access of threads to a common state.

If you want to split the state into a stream, you need to either declare different instances of this information (for example, classes) for the stream. for example, just create a new object in each Thread run() method or make a copy of the structure in question (for example, a deep copy of the collection)

An alternative is ThreadLocal research, in which each thread will have a different copy of the assigned resource.

+6
source

If you don't want your variable to be split, then don't use a global variable (you probably mean static in Java). Create a new field with a new object initialized when your thread starts. Example:

 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(); } } 

If you really need to access your local objects in your stream on different pieces of code, use 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(); } } 

What synchronization does is that it prevents the simultaneous entry of two threads into a synchronized block of code. This is also related to the exchange of variables between threads, but in another case, when you want them to be shared. Without synchronization, your changes from one thread may or may not be visible to other threads (see here and here )

+2
source

If I understand correctly, you should probably look at the final modifier:

 private final String s; 

This ensures that s cannot be changed, so your threads will not be able to change its value.

Also, make sure your threads are not trying to change values ​​that they are not using, copy them instead.

0
source

If you want to use static variables, you must use synchronized blocks for the class object inside your synchronized methods.

 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(); } } } 

}

Make sure all your static variables are accessible from the synchronized method / block in the class object , and not in the instance or this instance. The synchronized method you use is applicable to the this instance, this means that the current object with which you call the method and static variables are shared by all objects.

0
source

All Articles