2013-05-29 4 views
7

У меня есть класс Java, который запускает 2 отдельных потока. Первый поток запускается отлично, и все переменные правильны.Многопоточность Java и глобальные переменные

Когда я начинаю второй поток глобальные переменные из нити одного изменения значений, установленных в потоке 2.

Я попытался добавить синхронизированные блоки, где обновляются глобальные переменные, но это не сработало.

Есть ли способ решить эту проблему? Я хочу, чтобы каждый поток запускался и использовал свои собственные значения без помех в других значениях потока.

EDIT:

Отрывок из моего класса 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(); 
      } 

     } 
    } 
+2

i. е. удалите любую «статическую», которую вы, возможно, использовали – necromancer

+1

Вставка кода будет полезной – Mifeet

+1

Статические переменные распределяются между всеми экземплярами вашего «ConsumerIF» –

ответ

13

Статические переменные распределяются между всеми потоками, что делает их статическими. Если вы хотите использовать разные значения, используйте ThreadLocals или (намного лучше), используйте разные объекты с нестатическими переменными в потоках differrent. Без дальнейшего кода сложно сказать больше.

+0

Спасибо! Я удалил все статические переменные, и это сработало :) – lulu88

+0

Простой, но определяющий. :) – taruntejae

6

Синхронизация просто контролирует доступ Резьбы к общему состоянию.

Если вы хотите разделить состояние на поток, вам нужно либо объявить разные экземпляры этой информации (например, классы) для каждого потока. например просто создать экземпляр нового объекта в run() методы каждого Thread «s, или выполнить копию структуры в вопросе (например, глубокую копию коллекции)

Альтернатива является исследовать ThreadLocal, в котором каждая тема будет иметь другую копия назначенного ресурса.

0

Если я правильно понимаю, вы, вероятно, следует искать в модификаторе final:

private final String s; 

Это гарантирует, что s не может быть изменен, таким образом, ваши потоки не смогут изменить его значение.

Также убедитесь, что ваши потоки не пытаются изменить значения, которые они не используют, вместо этого скопируйте их.

+0

Не упоминается, что он не хочет вообще изменять, он просто не хочет другой поток для изменения. –

+0

Я все еще читаю сообщение, и я не могу решить, что он делает и чего хочет. «Я хочу, чтобы каждый поток запускался и использовал свои собственные значения без помех в других значениях потока». звучать как окончательный и/или копировать для меня. Но может быть просто, что его переменные статичны и не должны. – Djon

+0

Я девушка :) lol, но да посмотрите фрагмент выше - он меняет, я просто не хочу, чтобы другие потоки меняли мои текущие значения потоков – lulu88

2

Если вы не хотите, чтобы ваша переменная была разделена, то не используйте переменную global (вы, вероятно, имеете в виду static в Java). Создайте новое поле с новым объектом, инициализированным при запуске вашего потока. Пример:

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)

+0

Спасибо! Я удалю статические переменные? И посмотрите на ThreadLocal? – lulu88

+1

@ lulu88 При взгляде на ваш код нужно просто удалить 'static'. – Mifeet

0

Если вы хотите использовать статические переменные, вы должны использовать синхронизированные блоки для объекта класса внутри ваших синхронизированных методов.

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 экземпляра. Используемый вами синхронизированный метод применим к объекту this, это означает, что текущий объект, с которым вы вызываете метод, и статические переменные совместно используются всеми объектами.

Смежные вопросы