簡體   English   中英

如何在另一個線程JAVA中訪問volatile變量

[英]How can I access a volatile variable in another thread JAVA

我正在嘗試從多個運行線程訪問變量。

我有一個啟動2個線程的主類,一個生產者和一個消費者。

PRODUCER線程讀取一個二進制文件。 生產者線程為該二進制文件中的每一行創建一個對象,然后通過阻塞隊列將該對象傳遞給使用者線程。

然后,消費者將通過阻塞隊列傳入的對象獲取,並將該對象中字段的值輸出到文本文件。

有時,生產者線程正在讀取的二進制文件中有錯誤。

當二進制文件中有太多錯誤時,我希望使用者線程更改輸出到.err的txt文件的擴展名

我的問題:我不知道如何從使用者線程中的生產者線程修改值。 我一直在閱讀,我可以使用一個可變字段。 但是我不知道在線程之間使用它的正確方法是什么。

這是我的代碼的非常簡化且不太復雜的示例:

public class Main 
{

   private volatile static boolean tooManyErrors= false; 

    public static void main(String[] args) 
   {

        BlockingQueue<binaryObject> queue = new LinkedBlockingQueue<>(null);

        binaryObject poison = null;

        new Thread(new Producer(tooManyErrors, queue, poison)).start();
        new Thread(new Consumer(tooManyErrors, queue, poison)).start();

    }
}

public class Producer implements Runnable 
{

    private final BlockingQueue<binaryObject> queue;
    private final binaryObject POISON;
    private boolean tooManyErrors;

    private int errorsCounter = 0;

    public Producer(boolean tooManyErrors, BlockingQueue<binaryObject> queue, 
    binaryObject POISON) 
    {
        this.tooManyErrors = tooManyErrors;
        this.queue = queue;
        this.POISON = POISON;
    }

    @Override
    public void run() 
    {

        try 
        {
            process();
        } 
        catch (InterruptedException e) 
        {
            Thread.currentThread().interrupt();
        }
        finally 
        {
            while (true) 
        {
                try 
                {
                    queue.put(POISON);
                    break;
                } 
                catch (InterruptedException e) 
                {
                    //...
                }
            }
        }

    }

    private void process() throws InterruptedException 
    {
       //here is where all the logic to read the file and create
       //the object goes in. counts the number of errors in the file
       //if too many errors, want to change the tooManyErrors to true       

       if(errorsCounter > 100)
       {
          tooManyErrors = true;
       }

    }

}


public class Consumer implements Runnable 
{

    private final BlockingQueue<binaryObject> queue;
    private final binaryObject POISON;
    private boolean tooManyErrors;

    //variable with extension name
    private String extension;

    public Consumer(boolean tooManyErrors, BlockingQueue<Integer> queue, 
    binaryObject POISON) 
    {
        this.tooManyErrors = tooManyErrors;
        this.queue = queue;
        this.POISON = POISON;
    }

    @Override
    public void run() 
    {

        try 
        {
            while (true) 
            {
                binaryObject take = queue.take();
                process(take);

                // if this is a poison pill, break, exit
                if (take == POISON) 
                {
                    break;
                }
            }
        } 
        catch (InterruptedException e) 
        {
            Thread.currentThread().interrupt();
        }

    }

    private void process(Integer take) throws InterruptedException 
    {
        //this is where all the logic goes that takes the binaryObject
        //grabs all the fields from it such as binaryObject.getFileName,
        //happens. It then outputs a text file with all the fields grabbed
        //from the object. If the producer thread found too many errors
        // I want the extension changed to .err instead of .txt
        // I dont know how to do that

       if(tooManyErrors == false)
       {
           extension = ".txt";

           createFile(extension);
       }
       else
       {
           extension = ".err";

           createFile(extension);
       }
    }

   private void createFile(String extension)
   {
     //...
   }

}

好,這里有幾件事。 我假設只有一個生產者和一個消費者。 如果是這種情況,則可以將類生產者和消費者標記為static 如果將類標記為static ,則將僅存在其字段的一個實例-它將是單例。 您可以將生產者和使用者的任何字段標記為非私有,並且只需訪問這些字段即可。 somethingINeed = Producer.fieldThatIsNotPrivate來自使用者內部,反之亦然。

另一種選擇是保留要處理的對象的句柄並將其傳遞給構造函數。

Producer p = new Producer(tooManyErrors, queue, poison);
Consumer c = new Consumer(tooManyErrors, queue, poison);
p.setConsumer(c);
c.setProducer(p);
new Thread(p).start();
new Thread(c).start();

您可以為需要共享信息的任何字段創建訪問器。

暫無
暫無

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

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