簡體   English   中英

將數據傳遞到正在運行的線程的正確方法是什么

[英]What is the correct way to pass data to a running thread

在大多數情況下,創建線程時,可以預先准備數據並將其傳遞到構造函數或方法中。

但是,在打開套接字連接的情況下,通常已經創建了一個線程,但希望告訴它執行某些操作。

基本思路:

C#

private Thread _MyThread = new Thread(MyMethod);
this._MyThread.Start(param);   

Java

private Thread _MyThread = new Thread(new MyRunnableClass(param));
this._MyThread.start();

Now what?

那么,將數據傳遞給C#和Java中正在運行的線程的正確方法是什么?

Java的

您基本上可以擁有一個LinkedListLIFO )並進行如下操作(未經測試):

 class MyRunnable<T> implements Runnable {
     private LinkedList<T> queue;
     private boolean stopped;
     public MyRunnable(LinkedList<T> queue) { 
         this.queue = queue; 
         this.stopped = false; 
     }
     public void stopRunning() {
         stopped = true;
         synchronized (queue) {
             queue.notifyAll();
         }
     }
     public void run() {
         T current;
         while (!stopped) {
             synchronized (queue) {
                 queue.wait();
             }
             if (queue.isEmpty()) {
                 try { Thread.sleep(1); } catch (InterruptedException e) {}
             } else {
                 current = queue.removeFirst();

                 // do something with the data from the queue

             }
             Thread.yield();
         }
     }
 }

當您保留對參數中給出的LinkedList實例的引用時,在其他位置,您要做的就是:

 synchronized (queue) {
    queue.addLast(T);  // add your T element here. You could even handle some
                       // sort of priority queue by adding at a given index
    queue.notifyAll();
 }

將數據傳遞給正在運行的線程的一種方法是實現Message Queues 想要告訴偵聽線程做某事的線程會將一個項目添加到偵聽線程的隊列中。 偵聽線程以阻塞方式從該線程讀取。 沒有任何動作可等待。 每當另一個線程將消息放入隊列時,它都會提取該消息,具體取決於項目及其內容,然后您可以對其進行處理。

這是一些Java /偽代碼:

class Listener
{
   private Queue queue;
   public SendMessage(Message m)
   {
     // This will be executed in the calling thread.
     // The locking will be done either in this function or in the Add below
     // depending on your Queue implementation.
     synchronize(this.queue) 
     {
        this.queue.put(m);
     }
   }

   public Loop()
   {
     // This function should be called from the Listener thread.
     while(true) 
     {
        Message m = this.queue.take();
        doAction(m);
     }
   }

   public doAction(Message m)
   {
      if (m is StopMessage)
      {
        ...
      }
   }
}

和呼叫者:

class Caller
{
  private Listener listener;

  LetItStop()
  {
     listener.SendMessage(new StopMessage());
  }
}

當然,在編寫並行/並發代碼時,有很多最佳實踐。 例如,除了while(true)您至少應添加一個run :: Bool之類的字段,在收到StopMessage時可以將其設置為false。 根據您要實現該語言的語言,您將需要處理其他原語和行為。

例如,在Java中,您可能想使用java.util.Concurrent包來簡化您的工作。

編輯 :誤讀的問題,

C#我通常要做的是創建一個全局靜態類,然后在其中設置值。 這樣,您可以從兩個線程訪問它。 不知道這是否是首選方法,並且在某些情況下可能發生鎖定(如果我錯了,請糾正我),應該處理。

我還沒有嘗試過,但它也適用於線程池/ backgroundworker。

我能想到的一種方法是通過屬性文件。

好吧,這很大程度上取決於線程應該執行的工作。 例如,您可以讓一個線程等待一個事件(例如,ManualResetEvent),並在一個共享隊列中放置工作項(可以是要處理的數據結構,或者是遵循命令模式的更巧妙的命令)。 有人將新工作添加到隊列中,廣告會在事件發生時發出信號,從而使信號喚醒,從隊列中獲取工作並開始執行其任務。

您可以將此代碼封裝在自定義隊列中,在該隊列中,任何調用Deque方法的線程都將停止,直到有人調用Add(item)。

另一方面,也許您想依靠.NET ThreadPool類來發出要由池中的線程執行的任務。

這個例子有幫助嗎?

您可以使用委托模式,其中子線程訂閱事件,而主線程通過傳遞參數引發事件。

您可以在一個循環中運行輔助線程(如果這對您的要求有意義),並在每次循環執行時檢查一個標志。 該標志將由另一個線程設置,以向工作線程發出信號,通知某些狀態已更改,它也可以同時設置一個字段以傳遞新狀態。

此外,您可以使用monitor.wait和monitor.pulse發出信號,告知線程之間的狀態變化。

顯然,以上將需要同步。

暫無
暫無

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

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