2013-12-13 2 views
-1

어떻게 확인해야합니까?스레드간에 참조를 비동기 적으로 전달하는 방법은 무엇입니까? 옵저버와?

1) localThreadremoteThread은 서로 독립적으로 실행됩니까?

2.) localThreadremoteThread 사이의 메시지를 전달 하시겠습니까?

특히 localThread의 String 객체는 Telnet까지 "여과해야"합니다. 콜백으로 알려져 있습니다. 그러나 실제로는 본질적으로 아무 것도 없습니다. Telnet ~ observe. 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 : 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); 
     } 
    } 
} 

상태 유지.

답변

0

I 발견 용액 :

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

동시 패키지는 이런 종류의 물건에 많은 도움이 될 것입니다 : 당신은 단지 각 스레드 ConcurrentLinkedQueue를 줄 수 있습니다 때마다 그들이 행동하는 거기에 아무것도하시기 바랍니다 경우, 그들이 볼 수있는 큐를 확인할 수 있습니다 예를 들어 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html

. 한편 다른 스레드는 언제든지 큐에 새로운 개체를 추가 할 수 있습니다.

+0

롤, 그래,하지만 모든 진지하게, 나는 그것을 체크 아웃 하겠지만 ** 비동기 ** API가 있습니까? – Thufir

+1

방금 ​​설명한 내용은 비동기식입니다. 어느 쪽 스레드도 다른 스레드를 기다리지 않고, 그들이하는 일에 착수하고, 느낄 때마다 새로운 메시지를 확인합니다. –

1

코드가 채택 할 수있는 프로그래밍 패러다임에서 하나 개의 중요한 차이가있다 :

  • 동기 모드 : 수신 측이 명시 적으로있을 때 차단, 동시의 큐 항목을 소요 무한 루프를 실행은 준비된 항목 없음;

  • 비동기 모드 :받는 쪽에서 항목 교환 메커니즘에 콜백을 전송합니다. 이 콜백은 제작자 스레드에서 도착한 모든 항목에 대해 호출됩니다.

옵저버 패턴 느슨하게 아니라 이전에, 후자의 경우에 적용 할 수있다.

또한 후자의 경우 "항목 교환 메커니즘"은 일반적으로 동기 모드로 구현됩니다.

+0

예, 비동기 모드는 제가 수행 한 것입니다. – Thufir

+0

이벤트 디스패치 루프를 직접 구현 한 다음 콜백을 제출할 수 있습니다. 그것은 몇 줄의 코드 일뿐입니다. –

1

당신이하려고하는 것이 확실하지 않지만 스레드간에 데이터를 교환하려는 경우 다른 스레드가 변경 사항을 볼 수있게하려면 휘발성 변수가 필요합니다. AtomicReferences는 비 블로킹이며 여기서 도움이 될 API를 제공합니다.

+0

현재 코드는 github에 있습니다 : https://github.com/THUFIR/MudSocketClient/tree/master/src/mudsocketclient 물론 조금 다릅니다. 나는 당신이 여기 휘발성에 의하여 의미하는 무슨, 원자 참고를 의미하지 않는다. 내가 읽은 것에서 POJO CubbyHole은 두 개의 스레드 (?) 사이를 이동할 수 있어야합니다. 또는 오히려 두 개의 스레드로 액세스 할 수 있습니다. 그러나, 나는 Producer 스레드 만 실행을 계속하는 교착 상태 (?) 또는 아마도 Consumer를 차단하는 것으로 보입니다. 나는 잘 모르겠다. – Thufir

+1

비 휘발성 POJO의 경우, 한 스레드가 POJO를 변경하면 다른 스레드가 POJO를 변경할 수 있는지 여부와 그 시점을 언제 확인할 수 있습니다. Atomic *** 클래스는 그것에 기반하여 멋진 API를 배치합니다. 일반적으로 원래의 질문으로 되돌아 가면 두 스레드가 아무 것도 공유하지 않으면 서로 독립적으로 실행될 수 있습니다. 그러나 귀하의 경우에는 그렇게합니다. –

+0

예제 코드에서 CubbyHole의 메시지 필드는 휘발성이어야합니다. http://stackoverflow.com/questions/6259745/volatile-variable-in-java?rq=1 –