簡體   English   中英

Java多線程和全局變量

[英]Java multithreading and global variables

我有一個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();
            }

      }
  }

靜態變量在所有線程之間共享,這就是使它們成為靜態的。 如果要使用不同的值,請使用ThreadLocals或(更好),在不同的線程中使用具有非靜態變量的不同對象。 沒有進一步的代碼,很難說更多。

同步僅控制線程對共享狀態的訪問。

如果你想要每個線程單獨的狀態,那么你需要為每個線程聲明該信息的不同實例(例如類)。 例如,只需在每個Threadrun()方法中實例化一個新對象,或者執行相關結構的副本(例如集合的深層副本)

另一種方法是調查ThreadLocal ,其中每個Thread將具有指定資源的不同副本。

如果您不希望共享變量,則不要使用全局變量(您可能在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();
      }
 }

同步的作用是它阻止兩個線程同時進入同步的代碼塊。 它也與在線程之間共享變量有關,但在相反的情況下 - 當你想要它們共享時。 如果沒有同步,您對一個線程的更改可能會或可能不會被其他線程看到(請參閱此處此處

如果我理解正確,您應該查看final修飾符:

private final String s;

這可以確保無法修改s ,因此您的線程將無法更改其值。

還要確保您的線程不會嘗試修改它們不應該修改的值,而是復制它們。

如果要使用靜態變量,則應在同步方法中的類對象上使用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實例意味着您調用方法的當前對象和所有對象共享的靜態變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM