2014-07-24 20 views
-3

현재 IP 네트워크를 통해 원격 모니터링을위한 앱을 개발하고 있습니다. 네트워크의 각 노드는 센서 (전압, 전류, 온도 등)로부터 주기적으로 업데이트 된 데이터를 전송합니다.많은 스레드에서 데이터를 가져 오는 방법은 무엇입니까?

각 원격 객체를 처리하기위한 새로운 스레드를 시작합니다. 하지만 스레드에서 데이터를 전송하는 데 문제가 있습니다.

메인 스레드로 데이터를 전송하는 가장 좋은 방법은 무엇입니까? 내가 갖고있는 것과 다른 것을 가지고 가야할까요?

+2

일부 코드 – Hazaart

+1

을 게시하면 질문에 대답하기가 더 쉬울 수도 있습니다. "그러나 나는 트레드에서 데이터를 전송할 때 문제가 있습니다." 어떤 문제들? – Brandon

+1

"내가 가지고있는 것과 함께 가야합니까?"글쎄, 너는 무엇을 가지고 있니? – Korashen

답변

0

데이터를 BlockingQueue에 넣고 주 스레드에서 데이터를 가져 오십시오.

예 :

public class Producer implements Runnable { //this class puts objects with data into BlockingQueue 

private BlockingQueue<Object> queue; 

public Producer(BlockingQueue<Object> q) { 
    this.queue = q; 
} 

@Override 
public void run() { 
    //place fot your instruction 
    Object yourData = new Object(); 
    } 

    try { 
     queue.put(yourData); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

이 ExecutorService입니다와 미래 클래스를

1

이에 대한 일반적인 접근 방식을 BlockingQueue의에서

public class Consumer implements Runnable{ 

private BlockingQueue<Object> queue; 

public Consumer(BlockingQueue<Object> q){ 
    this.queue=q; 
} 

@Override 
public void run() { 
    try{ 
     Object date = queue.take() 
     // your operations witha data 

    }catch(InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

}

을 데이터를 읽거나 사용하는 클래스입니다 일종의 문제는 IO를 처리에서 분리하는 것이므로 귀하의 경우 당신은 소켓에서 읽기 스레드를 처리하고 처리하기 위해 작업자 스레드로 데이터를 전달합니다. NIO API는 사용자가 OS에 기본 스레드를 차단 방지하기 위해 필요한 스레딩을 남길 수 있습니다 의미 사용할 수있다 자바 7 이후 소켓 IO를 시작으로 소켓 IO

.

당신은 들어오는 연결을 수신하고이 같은 AsynchronousServerSocketChannelAsynchronousSocketChannel 사용하여 읽기 시작할 수 있습니다 다음 ReadHandler

private class AcceptAndReadHandler implements CompletionHandler<AsynchronousSocketChannel,Void> 
{ 
    public void completed(AsynchronousSocketChannel channel, Void attribute) 
    { 
    serverSocketChannel.accept(null, this); 

    ReadHandler readHandler = new ReadHandler(channel); 
    channel.read(readHandler.getBuffer(), Void, readHandler) 
    } 
} 

public class ReadHandler implements CompletionHandler<Integer,Void> 
{ 
    private ByteBuffer buffer; 

    public ReadHandler(AsynchronousSocketChannel channel) 
    { 
    this.channel = channel; 
    this.buffer = ByteBuffer.allocate(1024); 
    } 

    public ByteBuffer getBuffer() { return this.buffer; } 

    public void completed(Integer read, Void attribute) 
    { 
    byte[] data = new byte[read]; 
    buffer.get(data); 

    ... 

    ReadHandler readHandler = new ReadHandler(channel); 
    channel.read(readHandler.getBuffer(), Void, readHandler). 
    } 
} 

해야합니다 다음 CompletionHandler들과 같이 보일 것이다 어디

AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000)); 
serverSocketChannel.accept(null, new AcceptAndReadHandler()); 

을 전송 된 블록에 데이터가 수신된다는 보장이 없으므로 함께받은 데이터를 조각 낼 수있을 정도로 영리해야합니다.

두 가지 공통적 인 접근 방법은 각 메시지 앞에 길이를 사용하거나 구분 기호를 사용하는 것입니다. Netty과 같은 API를보고 싶을 수도 있습니다. 메시지를 다시 작성하기 위해 로직을 작성하지 않아도됩니다. 당신이 완료 메시지가 있으면

처리

, 당신은 그것을 처리 할 필요가있다. 그래서, 이것은 당신이 queue을 통과하기 위해 CompletionHandler의를 수정해야 할 것 작동하려면

public static void main(String[] args) 
{ 
    boolean running = true; 
    Runtime.getRuntime().addShutdownHook(() -> running = false); 

    BlockingQueue<byte[]> queue = new ArrayBlockingQueue<>(); 

    AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000)); 
serverSocketChannel.accept(null, new AcceptAndReadHandler(queue)); 

    while (running) 
    { 
    byte[] data = queue.take(); 
    ... 
    }  
} 

:이 작업을 수행하는 simiplest 방법은 코드가 같은 것을 보일 수 있도록 큐에 넣어하는 것입니다 ReadHandler이고data입니다.당신이 처리를 멀티 - 스레드하려면

, 당신은 다음과 같이 Executor을 사용해야합니다

public static void main(String[] args) 
{ 
    boolean running = true; 
    Runtime.getRuntime().addShutdownHook(() -> running = false); 

    Executor executor = Executors.newFixedThreadPool(10); 

    AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000)); 
serverSocketChannel.accept(null, new AcceptAndReadHandler(executor)); 

    while (running) 
    { 
    ... 
    }  
} 

을 다시 말하지만, 당신이를 통과 할 수 있도록은 CompletionHandler의 수정이 시간이 필요할 것 executorReadHandler이고 처리 논리는입니다.

두 가지 접근 방식간에 중요한 차이점은 멀티 스레드 예제에서는 처리 순서가 보장되지 않는다는 것입니다.

관련 문제