Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-单线程和多线程的压缩差异_Java_Multithreading_Compression_Gzip - Fatal编程技术网

Java-单线程和多线程的压缩差异

Java-单线程和多线程的压缩差异,java,multithreading,compression,gzip,Java,Multithreading,Compression,Gzip,所以我会在前面说,我的多线程程序无法输出gzip可以成功解压缩的东西,所以可能还有其他问题。但我注意到,单线程和多线程的每个块的压缩大小完全不同 在我的单线程运行中,我有一个带有SYNC\u FLUSH集的GZIPOutputStream(System.out,true)。我不断地从system.in读取数据,直到缓冲区已满 GZIPOutputStream compressor = new GZIPOutputStream(System.out, true); bytesRead = inBy

所以我会在前面说,我的多线程程序无法输出gzip可以成功解压缩的东西,所以可能还有其他问题。但我注意到,单线程和多线程的每个块的压缩大小完全不同

在我的单线程运行中,我有一个带有SYNC\u 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)));
    }
}
我想我所做的就是把压缩工作交给线程。我没有改变其他任何事情。然而,当我运行我的多线程程序并得到结果时,我注意到两个程序之间的每个块通常都有很大的不同。我使用了一个小的缓冲区和小的输入,所以它更容易读取

我的多线程程序出现了一个crc错误,这意味着gzip至少能够识别格式并开始解压缩。只是当它完成时,最终结果与它期望的CRC不匹配(比如解压缩输出的大小等等)

我真的不知道为什么会这样。我本以为会有更明显的错误,但这一次似乎太随机了。它确实在压缩。单线程程序和多线程程序之间的前几个字节(当然在头之后)通常是相同的,所以我不认为我的连接顺序不正确(加上executor.get()函数应该处理这个问题)

我只是被难住了。我知道gzip可以解压连接的流。我把我的输入一分为二,分别输出,然后在我的单线程程序中把它们结合起来,解压得很好

作为记录,我只是在一个328个“a”字符的文件上尝试了它,所以它不是很大。单个线程的GZIPOutputStream的hexdump是

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     
他们很不一样

哇,这真是太长了。很抱歉。真的很困惑和困惑。

从某个地方开始:

他们很不一样

如果我对注释的假设成立(对于两个字符串a,b,gzip满足unzip(gzip(a+b))=unzip(gzip(a)+gzip(b)),那么这是预期的行为

根据,每个gzip调用都会写入一个头。在:

标题将以:
1f 8b 80…

您可以在输出中清楚地看到这一部分(字节交换)。对于每个新的gzip部分,报头将再次启动。因此,分块输出的长度必须大于正常输出的长度

关于多线程问题:我需要一个完整的示例来查看发生了什么。

不需要
flush()
finish()
调用
close()
将完成,
flush()
调用只会向deflate流添加不必要的空块。因为不需要
flush()
,所以不需要将
syncFlush
设置为true,因为它不会做任何事情

制作一个大的gzip流和制作一堆小的gzip流当然会产生完全不同的结果。每个gzip流的头和尾都有18字节的开销。对于您正在使用的小模块,这种开销完全控制了结果


在您的线程示例中有一个很大的bug。虽然无线程示例压缩了328个“A”,但线程示例将“A”和换行字符(十进制10)混合在一起。也许你不需要尝试压缩就可以开始了,看看你是否可以分解一些输入(真实文本,而不仅仅是一系列相同的字符),将数据块发送给线程,让线程对数据什么都不做,然后正确地重建原始输入。一旦你能做到这一点,然后再回来。

你能提供一个可以运行的示例吗?看起来您在线程之间共享了缓冲区,这意味着内容可能非常随机。更重要的是,我不认为为每个部分创建一个新的GZIP是一个好主意。好的,如果GZIP对两个字符串a,b满足解压(GZIP(a+b))=解压(GZIP(a)+GZIP(b)),那么可以为每个部分使用新的GZIP实例。我没有从快速搜索中找到任何参考资料,但从逻辑角度来看,这是有意义的。因为gzip经常用于分块编码,比如http。
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     
private void writeHeader() throws IOException {
    out.write(new byte[] {
                  (byte) GZIP_MAGIC,        // Magic number (short)
                  (byte)(GZIP_MAGIC >> 8),  // Magic number (short)
                  Deflater.DEFLATED,        // Compression method (CM)
                  0,                        // Flags (FLG)
                  0,                        // Modification time MTIME (int)
                  0,                        // Modification time MTIME (int)
                  0,                        // Modification time MTIME (int)
                  0,                        // Modification time MTIME (int)
                  0,                        // Extra flags (XFLG)
                  0                         // Operating system (OS)
              });
}
private final static int GZIP_MAGIC = 0x8b1f;
public static final int DEFLATED = 8;