그래서 다중 스레드 프로그램이 gzip이 성공적으로 압축을 풀 수 없으므로 다른 문제가있을 수 있다는 내용을 말합니다. 그러나 내가 알아챈 점은 단일 스레드와 다중 스레드에 대한 각 블록의 압축 크기가 근본적으로 다릅니다.Java- 단일 스레드 및 다중 스레드에 대한 압축의 차이점
내 단일 스레드 실행에서 SYNC_FLUSH가 설정된 GZIPOutputStream (System.out, true)이 있습니다. 내 버퍼가 가득 찰 때까지 계속 system.in에서 읽습니다.
GZIPOutputStream compressor = new GZIPOutputStream(System.out, true);
bytesRead = inBytes.read(buff,0,BLOCK_SIZE);
....
while(bytesRead != -1)
{
offset += bytesRead;
if (offset == BLOCK_SIZE)
{
compressor.write(buff,0,offset);
compressor.flush();
offset = 0;
}
if((bytesRead=inBytes.read(buff,offset,BLOCK_SIZE-offset)) == -1) {
compressor.write(buff,0,offset);
compressor.finish();
}
}
compressor.close();
전체 버퍼가있는 것을 볼 수 있듯이 압축기에 출력을 쓰도록 요청한 다음 flush를 호출합니다. 이것은 내가 나머지 출력을 압축하고 플러시하도록 강요하므로, 다시 쓰려고 할 때 버퍼에 남아있는 데이터가 없습니다.
원본 입력이 길이로 시작된 것처럼 (즉, 각 블록이 개별 스트림이므로) 매우 비슷합니다.
내 멀티 스레드 프로그램에서 하나의 GZIPOutputStream을 쓰고 플러시하는 대신 각자 자신의 GZIPOutputStream을 가진 많은 스레드가 있습니다. 그래서 기본적으로 해당 부분을 스레드 호출로 바꿉니다.
List<Future<byte[]>> results = new ArrayList<Future<byte[]>>();
bytesRead = inBytes.read(buff,0,BLOCK_SIZE);
while(bytesRead != -1)
{
offset += bytesRead;
if (offset == BLOCK_SIZE)
{
results.add(exec.submit(new workerThread(buff,offset)));
offset = 0;
}
if((bytesRead=inBytes.read(buff,offset,BLOCK_SIZE-offset)) == -1) {
results.add(exec.submit(new workerThread(buff,offset)));
}
}
여기서 나는 압축하기 위해 버퍼를 전달합니다. 내 모든 스레드
private ByteArrayOutputStream bOut = new ByteArrayOutputStream();
private byte[] finalOut;
....
public byte[] call() {
try{
GZIPOutputStream compress = new GZIPOutputStream (bOut, true);
compress.write(input,0,size);
compress.flush();
compress.close();
}
catch (IOException e)
{
e.printStackTrace();
System.exit(-1);
}
finalOut = bOut.toByteArray();
return finalOut;
}
나는 모든 말 그대로 스레드에 압축 작업을 부여했던 생각하면됩니다. 나는 다른 것을 바꾸지 않았다. 그러나, 내가 멀티 스레드 프로그램을 실행하고 결과를 hexdump하면, 각 블록은 일반적으로 두 프로그램 사이에 많은 차이가 있음을 발견했습니다. 작은 버퍼와 작은 입력을 사용하여 더 쉽게 읽을 수있었습니다.
내 멀티 스레드 프로그램에서 crc 오류가 발생합니다. 이는 적어도 gzip이 형식을 인식하고 압축을 풀기 시작한다는 것을 의미합니다. 완료되면 최종 결과가 CRC에서 예상 한 것과 일치하지 않습니다 (예 : 압축 해제 된 출력의 크기 등).
나는 왜 이런 일이 발생하는지 솔직하게 알지 못합니다. 나는 훨씬 더 명백한 오류를 예상했을 것이다. 그러나 이것은 매우 무작위로 보인다. 그것은 확실히 압축하고 있습니다. 그리고 단일 스레드 및 다중 스레드 프로그램 사이의 첫 번째 몇 바이트 (물론 머리글 다음)는 종종 동일하므로 순서가 틀렸다고 생각하지 않습니다 (executor.get() 함수도 처리해야 함) .
나는 방금. gzip이 연결 스트림을 압축 해제 할 수 있음을 알고 있습니다. 저는 문자 그대로 입력을 절반으로 나누었고 그것을 개별적으로 출력 한 다음 싱글 스레드 프로그램에서 그들을 결합 시켰습니다.
레코드의 경우 328 "A"문자가있는 파일에서 시도해 보았으므로 그다지 큰 파일은 아닙니다. 단일 스레드에 대한 GZIPOutputStream의 16 진 덤프는
0000000 8b1f 0008 0000 0000 0000 7472 581c 0000
0000010 0000 ffff 681a 0004 0000 ffff 21a2 02e2
0000020 0000 ff00 03ff a800 5bff 5c79 0001 0000
입니다 그리고 멀티 스레드 것이
0000000 8b1f 0008 0000 0000 0000 7472 19a4 22e0
0000010 1146 0000 ff00 03ff 7500 5f6c 80d1 0000
0000020 1f00 088b 0000 0000 0000 a200 e221 4622
0000030 0011 0000 ffff 0003 6c75 d15f 0080 0000
0000040 8b1f 0008 0000 0000 0000 21a2 02e2 0000
0000050 ff00 03ff 8a00 193b 5c21 0000 0000
그들은 매우 다른 것입니다.
와우는 정말 길었습니다. 미안합니다. 그냥 정말 의아해하고 붙어.
실행할 수있는 예제를 제공 할 수 있습니까? 스레드간에 버퍼를 공유하는 것처럼 보이므로 내용이 매우 혼란 스럽습니다. 더군다나, 모든 부분에 대해 새로운 GZIP를 만드는 것이 좋은 생각이라고 생각하지 않습니다. –
두 개의 문자열 a, b에 대해 gzip이 unzip (gzip (a + b)) = unzip (gzip (a) + gzip (b))을 만족하면 모든 파트에 대해 새 gzip 인스턴스를 사용할 수 있습니다. 나는 빠른 검색에서 어떤 참고 문헌도 찾지 못했지만 논리적 인 관점에서 볼 때 그것은 의미가있다. gzip은 http와 같이 청크 분할 인코딩에 많이 사용되기 때문입니다. –