2013-11-20 4 views
1

요청한 문자열을 에코 인쇄하는 에코 서버를 만들어야합니다. 한 스레드 (클라이언트)는 echo 메서드를 호출하여 에코 할 문자열을 전송하고 (실제로 모든 echo 메서드는 문자열을 작업 큐에 배치 함) 별도의 스레드가 대기열에서 문자열을 큐에서 빼낸 다음 화면에 출력합니다. 단계Java 다중 스레드 동기화

하나는이 스레드간에 공유하기 위해 큐 정적 만드는 것이었다 나는 간단하게 대체하여 이런 짓을 :

public final Queue<String> requests = new LinkedList<String>(); 

을 (올바른 경우 확실하지)

public static Queue<String> requests = new LinkedList<String>(); 

public class EchoServer implements Runnable { 

//make queue a static object 
//public final Queue<String> requests = new LinkedList<String>(); 
public static Queue<String> requests = new LinkedList<String>(); 

public EchoServer() { 
    new Thread(this).start(); 
} 

//all echo does is place the string in the job queue 
public void echo(String s) { 
    requests.add(s); 
} 

public void run() { 
    for(;;) realEcho(requests.remove()); 

    //synchronized here? 
} 

private void realEcho(String s) { 
// do the real work of echo-printing 
} 

    public static void main(String[] args) { 
    System.out.println(Thread.currentThread().getName()); 
    EchoServer r1 = new EchoServer(); 
    r1.echo("HEY"); 
    Thread t1 = new Thread(r1, "manager"); 
    t1.start(); 


    EchoServer r2 = new EchoServer(); 
    r2.echo("HI"); 
    Thread t2 = new Thread(r2, "client"); 
    t2.start(); 

    } 

}

:이 코드에서

"NoSuchElement"예외 외에는 아무 것도 추가하지 않고 모든 스레드가 요소를 요청 큐에서 제거하려고하기 때문에이 문제가 발생합니다. 큐가 여러 스레드에서 공유되기 때문에 동기화 문제를 처리해야합니다. 동기화를 알아 내려고 할 때 나는 매우 길다. 누군가는 저를 도울 수있는 몇몇 끝이 있는가? 어떤 도움을 주셔서 감사합니다!

답변

2

LinkedList은 스레드로부터 안전하지 않습니다.

대신 ConcurrentLinkedQueue을 사용하십시오.

BlockingQueue을 사용하십시오. 큐에 항목이있을 때까지 차단하는 추가 방법 take()을 제공한다는 점만 다를뿐입니다. 그렇게하면 큐를 계속해서 다시 검사하지 않고 여분의 프로세서 사이클을 모두 먹어서 마지막으로 확인한 이후 마지막 50 나노초에 새 항목을 추가했는지 확인할 수 있습니다. 예를 들어
:

public static void main(String[] args) { 

    EchoServer clientEchoServer = new EchoServer(), \ 
       managerEchoServer = new EchoServer(); 

    managerEchoServer.start(); 
    managerEchoServer.echo("HI!"); 

    Thread manager = new Thread(managerEchoServer, "manager"); 
    manger.start(); 


    clientEchoServer.start(); 
    clientEchoServer.echo("HI!"); 

    Thread client = new Thread(managerEchoServer, "manager"); 
    client.start(); 

} 
+0

+1 BlockingQueue''를 들어 (가 BTW'ConcurrentBlockingQueue' 아니다) : 주요 방법

public class EchoServer implements Thread { public static BlockingQueue<String> requests = new LinkedBlockingQueue<>(); public void echo(String s) { if(isInterrupted()) throw new IllegalStateException("Queue is closing!"); requests.add(s); } @Override public void run() { try( while(!isInterrupted() || requests.peek()!=null) processEchoRequest(requests.take()); } catch (InterruptedException e) {} } private void processEchoRequest(String s) { /* [...] */ } } 

변수는 정말 이름을 변경해야합니다. 사용하기 쉬운 구현은'LinkedBlockingQueue'입니다. – Gray

+0

감사합니다. 이것은 매우 도움이됩니다! '심볼을 찾을 수 없습니다. 심볼을 찾을 수 없습니다. 심볼 : 메소드 isInterrupted()' 이 함수를 작동 시키려면 아무 것도 포함해야합니까? – user2125844

+0

@ user2125844'isInterrupted()'는'java.lang.Thread'의 한 메소드입니다. 내 코드는'Runnable'보다는'Thread'를 확장합니다. – AJMansfield