2013-12-13 37 views
-1

如何保證:如何在線程之間異步傳遞引用?觀察員?

1)localThread和運行相互獨立的remoteThread

2.)在localThreadremoteThread之間傳遞消息?

具體來說,localThread中的字符串對象需要「滲透」到Telnet,我認爲它被稱爲回調。然而,對於Telnetobserve本身沒有任何實質性的東西。這是對LocalIO的匿名引用,我沒有看到明確提供引用有幫助。

我已閱讀約java.util.concurrent.Semaphore,直到我的頭爆炸,所有我走開的是,它似乎並不適用。對於這兩個線程,無論其他線程在做什麼,它們都應該繼續運行。但是,需要一些機制來在線程之間傳遞對象引用...

public class Telnet { 

    public Telnet() throws InterruptedException { 
     startThreads(); 
    } 

    public static void main(String[] args) throws InterruptedException { 
     new Telnet(); 
    } 

    public void startThreads() throws InterruptedException { 
     Semaphore s = new Semaphore(1, true); 

     Thread localThread = new Thread(new LocalIO()); 
     Thread remoteThread = new Thread(new RemoteIO()); 

     localThread.start(); 
     remoteThread.start(); 
    } 
} 

線程本身如下。 LocalIO

public class LocalIO implements Runnable { 

    @Override 
    public void run() { 
     Scanner scanner; 
     String line; 
     while (true) { 
      scanner = new Scanner(System.in); 
      line = scanner.nextLine(); 
      out.println("\n\nyou entered\t\"" + line + "\"\n"); 
     } 
    } 
} 

RemoteIO

public class RemoteIO implements Runnable { 

    private static Logger log = Logger.getLogger(RemoteIO.class.getName()); 
    final String host = "rainmaker.wunderground.com"; 
    final int port = 3000; 

    @Override 
    public void run() { 
     log.fine(host + port); 
     int byteOfData; 
     try (Socket socket = new Socket(host, port); 
       InputStream inputStream = socket.getInputStream(); 
       OutputStream ouputStream = socket.getOutputStream(); 
       PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true); 
       final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) { 
      while ((byteOfData = inputStream.read()) != -1) { 
       out.print((char) byteOfData); 
      } 
     } catch (Exception e) { 
      out.println(e); 
     } 
    } 
} 

牢記RemoteIO永遠不會關閉它的連接,並無限期地運行。

回答

0

我發現的溶液:

public class RemoteConnection extends Observable { 

    private static Logger log = Logger.getLogger(RemoteConnection.class.getName()); 
    private final Socket socket; 
    private final BufferedInputStream in; 
    private final BufferedOutputStream out; 
    private final static String UTF8 = "UTF-8"; 

    public RemoteConnection(String host, int port) throws UnknownHostException, IOException { 
     socket = new Socket(host, port); 
     in = new BufferedInputStream(socket.getInputStream()); 
     out = new BufferedOutputStream(socket.getOutputStream()); 
    } 

    public void write(Deque<String> commands) throws IOException { 
     String command; 
     while (!commands.isEmpty()) { 
      command = commands.pop(); 
      out.write(command.concat("\r\n").getBytes(Charset.forName(UTF8))); 
      log.info(command); 
     } 
     out.flush(); 
    } 

    void read() { //probably should use BufferedStream to better effect..? 
     Thread readRemote = new Thread() { 

      @Override 
      public void run() { 
       StringBuilder sb = new StringBuilder(); 
       char ch; 
       int i; 
       while (true) { 
        try { 
         i = in.read(); 
         ch = (char) i; 
         sb.append(ch); 
         System.out.print(ch); 
         if (i == 13) { 
          setChanged(); 
          notifyObservers(sb.toString()); 
          log.fine(sb.toString()); 
          sb = new StringBuilder(); 
         } 
        } catch (IOException ioe) { 
         log.fine(ioe.toString()); 
        } 
       } 
      } 
     }; 
     readRemote.start(); 
    } 
} 

通過重組穿線,這近似於差芒遠程登錄,與異步線程的I/O。我認爲從控制檯讀取阻塞...東西...

我真的不知道爲什麼這個工程,但其他方法沒有。我寧願讓主類啓動並處理線程,並在線程之間傳遞引用,但是儘管使用了這裏提供的各種解決方案,但仍然無法正常工作。

LocalConnection有一個類似的線程方法。

2

concurrent包是這樣的事情非常有幫助: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html

例如,您可以把每個線程的ConcurrentLinkedQueue,他們可以檢查隊列,看看是否有什麼就採取行動時,他們請。與此同時,其他線程可以隨時將新對象添加到隊列中。

+0

大聲笑,是的,但一切認真,我會檢查出來,但有**異步** API? – Thufir

+1

我剛剛描述的是異步的。兩個線程都不會等待對方,他們只是繼續他們正在做的事情,並在他們感覺喜歡時檢查新消息。 –

1

有一個在編程範式一個本質上的區別你的代碼可以採用:

  • 同步模式:接收端運行一個無限循環,其中明確需要的項目掀起了併發隊列,當有阻塞沒有物品準備好;

  • 異步模式:接收端向物品交換機制提交回調。對於從生產者線程到達的每個項目都會調用此回調函數。

觀察員模式可以寬鬆地適用於後一種情況,而不是前者。

另請注意,在後一種情況下,「項目交換機制」通常以同步模式實現。

+0

是的,異步模式是我所追求的。 – Thufir

+0

您可以實現您自己的事件分派循環,然後向其提交回調。它只是幾行代碼。 –

1

不知道你在做什麼,但是如果你想在線程之間交換數據,你需要一個volatile變量來確保其他線程看到變化。 AtomicReferences是非阻塞的,並提供了一些可能在這裏幫助的API。

+0

當前的代碼在github上:https://github.com/THUFIR/MudSocketClient/tree/master/src/mudsocketclient當然,它現在有點不同了。我不確定你在這裏的意思是什麼,也不是原子參考。從我讀到的,POJO CubbyHole應該能夠在兩個線程之間切換(?)。或者,可以通過兩個線程訪問。但是,我似乎處於一個死鎖(?),只有Producer線程繼續運行 - 或者它可能會阻止使用者。我不確定。 – Thufir

+1

對於非易失性POJO,如果一個線程對POJO所做的更改對另一個線程可見,則不能保證jvm。原子***類基於此,並在其周圍放置一個不錯的API。一般來說,回到你的原始問題,你只能確保兩個線程獨立運行,如果他們沒有共享任何東西。但就你而言,他們的確如此。 –

+0

因此,在您的示例代碼中,CubbyHole的消息字段應該是易失性的。 http://stackoverflow.com/questions/6259745/volatile-variable-in-java?rq=1 –

相關問題