近期本人在android开发中遇到大文件下载时阻塞问题. 客户端要下载一个文件,但每次下载到固定字节数就阻塞在那里,过一会儿就抛出SocketTimeoutException。
譬如这个文件的大小为18M,用inputStream.read(buf)的方式从socket端读取数据,每次从0读到5M的时候就阻塞在那里。
我分别使用了1,2,3 个线程去读取文件,每次都是阻塞在5M那里:
1个线程时,负责读取0-18M, 读取5M时就阻塞在那里.
2个线程时,第一个线程负责前9M,第二个线程负责后9M 。结果时后面线程已经完成9M下载,前面线程还停留在5M。跟1个线程时状态一样,只不过多下了后面9M.
3个线程,第一个线程负责下载0-6M, 第二个线程成负责下载6-12M, 第三个线程负责下载12-18M。结果跟2个线程状态一样,后面两个线程12M下载完了, 第一个线程仍然卡在5M的地方
其中部分代码如下:
conn = (HttpURLConnection) url.openConnection();
conn.setAllowUserInteraction(true);
conn.setRequestMethod("GET");
conn.setReadTimeout(timeout * 1000);
conn.setConnectTimeout(timeout * 1000);
// 设置当前线程下载的起点,终点
conn.setRequestProperty("Range", "bytes=" + curPosition + "-"
+ endPosition);
// 使用java中的RandomAccessFile 对文件进行随机读写操作
File file = new File(fileName);
outputStream = new RandomAccessFile(file, "rw");
// 设置开始写文件的位置
outputStream.seek(curPosition);
inputStream = conn.getInputStream();
我还试着跳过5M那个字节,直接从5M+1后面的字节读起,后面的文件内容还是可以下载下来了。但是下载文件时不允许跳过一个字节的。
好奇怪一呀?如果说是客户端的问题,用相同代码下载其他文件是可以成功下载的;若是服务端问题,用同样链接在PC上是可以正常下载的。
难道5M那里有什么特殊字符, 导致每次读到5M就卡壳了?
百思不得其解。最后我试着用4个线程分段下载18M文件,每个线程负责4.5M, 没想到这次竟然成功了。太神奇了!
很显然,分四个线程下,第一个线程负责下载0到4.5M,第二个线程负责4.5-9M, 依次类推。这里,第二个线程从4.5M读到5M 时竟然没有阻塞,还能顺利把后面下载继续完成。
为什么连续0-5M阻塞, 而从断点4.5M到5M就不阻塞了?
真是好奇怪现象,这个read(buf) 阻塞的问题困惑快一周了。最后只是通过修改下载线程数暂时解决了下载问题。但是没找到真正的阻塞原因,以后估计还会碰上。
所有各位懂行的看官,如果知道这种阻塞原因,还请不吝赐教!