이 코드 세그먼트에서 파이프를 만들고 한쪽 끝에 스캐너를 연결하고 다른 소비자와 생산자 스레드간에 통신하기 위해 다른 끝에 PrintStream을 연결합니다. 그런 다음 세 개의 스레드를 만들고 시작합니다.Java : 스트림을 통해 통신하는 두 개의 스레드가 회사이고, 세 명이 군중입니다.
첫 번째 스레드는 소비자 스레드입니다. Scanner를 검사하여 텍스트 줄이 소비되고, 소비하고, 표준 출력으로 인쇄 한 다음 몇 밀리 초 동안 대기 한 다음 반복합니다. 소비 할 것이 없다면, 그것에 관한 메시지를 출력하고, 잠자기를 반복합니다.
이 코드 세그먼트의 두 번째 스레드는 아무 작업도 수행하지 않습니다. 아래에 그 이상.
2.5 세 번째 스레드가 시작되기 전에 3 초의 지연이 있습니다.
- 세 번째 스레드는 생산자이며 첫 번째 스레드가 소비 할 텍스트 메시지를 생성합니다. 이 메시지를 생성합니다 (I 예상대로)
public static void main(String[] args) throws IOException
{
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
Scanner scan = new Scanner(pis);
PrintStream ps = new PrintStream(pos);
new Thread()
{
public void run()
{
int x = 0;
while (true)
{
x++;
if (scan.hasNextLine())
{
System.out.println("pulled: " + scan.nextLine());
} else
{
if (x % 100 == 0)
{
System.out.println("no data to pull");
}
}
try
{
sleep(10);
} catch (InterruptedException ex) { }
}
}
}.start();
new Thread()
{
public void run()
{
}
}.start();
try
{
sleep(3000);
} catch (InterruptedException ex) { }
new Thread()
{
public void run()
{
int x = 0;
while (true)
{
x++;
ps.println("hello: " + x);
try
{
sleep(1000);
} catch (InterruptedException ex) {}
}
}
}.start();
}
에게 출력을 잠들지 : 전혀 있기 때문에
가pulled: hello: 1
pulled: hello: 2
pulled: hello: 3
pulled: hello: 4
pulled: hello: 5
pulled: hello: 6
는 또한합니다 (scan.nextLine()를 차단하고 있습니다 없습니다 사용할 수있는 데이터가 없음을 나타내는 메시지 ... 데이터는 "진행 중"인 경우에도 항상 "사용 가능"입니다. 내가 소비하는 첫 번째 스레드에 대한 텍스트를 생성하는 몇 가지 코드 2 스레드의 몸을 교체하는 경우
지금, :
new Thread()
{
public void run()
{
ps.println("Interfere");
}
}.start();
은 그 때 나는 첫 번째 스레드의 데이터가없는 절을 트리거하기 시작합니다 두 번째 스레드가 메시지를 생성 할 수의 PrintStream 객체를 사용하여 시작하면
pulled: Interfere
no data to pull
no data to pull
no data to pull
no data to pull
no data to pull
no data to pull
no data to pull
no data to pull
그래서 뭔가는 파이프에 잘못 소비자 스레드는 다른 쪽 끝에서 메시지를 찾을 수있는 중지합니다.
이제 상황이 더 이상합니다. 내가 마무리에서 두 번째 스레드를 방지하면, 정말로 긴 루프를 던져 말을 한 후 파이프는 최대 풀칠되지 않습니다
이new Thread()
{
public void run()
{
ps.println("interfere");
for (long i = 0; i < 10000000000L; i++);
System.out.println("done interfering");
}
}.start();
출력 :
pulled: interfere
pulled: hello: 1
pulled: hello: 2
done interfering
pulled: hello: 3
pulled: hello: 4
pulled: hello: 5
pulled: hello: 6
그래서 나는 경우라고 생각 두 번째 스레드는 세 번째 스레드가 생성을 시작하기 전에 종료되고 첫 번째 스레드는 세 번째 스레드에서 메시지를 얻지 않습니다. 그러나 세 번째 스레드가 생성을 시작할 때까지 두 번째 스레드가 응답하지 않으면 모든 것이 예상대로 진행됩니다.
여기 무슨 일 이니? 종료 할 때 두 번째 스레드가 파이프/스트림을 닫고 있습니까 (또는 파이프/스트림에서 다른 동작을 수행합니까?)? 그렇다면 왜? 그리고 두 번째 스레드가 종료되기 전에 세 번째 스레드가 파이프/스트림을 사용하기 시작하면 왜 파이프/스트림을 닫는 것처럼 보이지 않습니까?두 번째 스레드가 메시지를 생성하고 세 번째 스레드가 시작되기 전에 종료 될 때 예상대로이 코드를 "작업"하게 만드는 방법이 있습니까?
배경 : 이것은 여러 클라이언트가 단일 제작자 스레드의 메시지를 소비하는 시스템의 핵심 구성 요소입니다. 그러나 모든 클라이언트 스레드가 준비되었음을 신호 할 때까지 프로듀서 스레드를 시작할 수 없습니다. 각 클라이언트 스레드에 대해 준비가되었는지 여부를 쿼리하는 다른 스레드가 있습니다. 모든 클라이언트 스레드가 준비되었음을 알리면 생성자 스레드가 시작됩니다. 스트림을 통해 스레드가 통신하도록 노력 중이므로 나중에 여러 컴퓨터에 배포 할 수 있고 소켓을 사용하여 파이프를 최소한의 변경 사항으로 기본 코드에 설정할 수 있습니다. 여기서도 대안 솔루션 전략을 제안 해 주실 수 있지만 위의 솔루션이 작동하지 않는 이유를 알고 싶습니다.
당신의 잠은 무의미하다. 'hasNextLine()'은 이미 존재하는 라인이나 스트림의 끝이 없다면 블록 될 것이다. – EJP
코드를 살펴본 지 오래되었지만'PipedInput/OutputStream'은 두 스레드가 사용하도록 명시 적으로 작성 될 수 있다고 생각합니다. 동시 차단 대기열을 대신 사용해 보셨습니까? – erickson