Python多线程下载,支持断点续传(条件:不能删除临时文件),可以将该代码作为模块使用
注意点:1.读取网络文件时,最好设定read(size)参数,避免出现溢出或无法读取情况
2.线程一般情况下是越多越好,但太多会出现线程切换开销
#coding=utf-8
'''
多线程下载
'''
import sys
import os
import time
import urllib
from threading import Thread
class MyPythonThread(Thread, urllib.FancyURLopener): #初始化线程
def __init__(self, threadname, url, filename, ranges=0, proxies={}):
Thread.__init__(self, name=threadname)
urllib.FancyURLopener.__init__(self, proxies) #打开连接形式 是否使用代理
self.name = threadname #线程名
self.url = url #线程文件链接
self.filename = filename #存放线程下载内容的文件名
self.ranges = ranges #需要下载的文件的范围
self.downloaded = 0 #已下载的文件大小
def run(self): #start时隐式调用
try:
self.downloaded = os.path.getsize( self.filename ) #读取已下载临时文件的大小 用于断点续传
except OSError:
self.downloaded = 0
self.startpoint = self.ranges[0] + self.downloaded #重新下载的起始点
#若起始点大于本线程的需要下载的范围上限 证明下载已完成
if self.startpoint >= self.ranges[1]:
print 'Part %s has been downloaded over.' % self.filename
return
self.oneTimeSize = 32768 #32kByte/time 每次下载32KB
print 'task %s will download from %d to %d' % (self.name, self.startpoint, self.ranges[1])
self.addheader("Range", "bytes=%d-%d" % (self.startpoint, self.ranges[1]))
self.urlhandle = self.open( self.url ) #获得句柄
data = self.urlhandle.read(self.oneTimeSize) #每次读取self.oneTimeSize大小的数据 最好设定值 若不设置 默认全部读取 若文件特别大 出现读不到文件情况
while data:
filehandle = open( self.filename, 'ab' ) #ab以二进制追加模式打开 ab+以二进制读写模式打开
filehandle.write( data )
filehandle.flush()
filehandle.close()
self.downloaded += len( data )
data = self.urlhandle.read(self.oneTimeSize) #继续读取文件
def GetUrlFileSize(url, proxies={}):
# urlHandler = urllib.urlopen( url, proxies=proxies ) #使用代理打开连接
urlHandler = urllib.urlopen(url)
headers = urlHandler.info().headers #数据获得头部
length = 0
for header in headers:
print header
if header.find('Length') != -1: #找到头部中的Content-Length信息
length = header.split(':')[-1].strip() #strip()去掉前后空格
length = int(length)
return length
def SpliteBlocks(totalsize, blocknumber): #分片
blocksize = totalsize/blocknumber #每个线程处理的文件大小
ranges = [] #处理文件的范围存入到列表中
for i in range(0, blocknumber-1):
ranges.append((i*blocksize, i*blocksize +blocksize - 1))
ranges.append(( blocksize*(blocknumber-1), totalsize -1 ))
return ranges
def islive(tasks):
for task in tasks:
if task.isAlive():
return True
return False
def download(url, output, blocks=6, proxies={}): #proxies = local_proxies 默认6个线程
size = GetUrlFileSize( url, proxies )
ranges = SpliteBlocks( size, blocks )
threadname = [ "thread_%d" % i for i in range(0, blocks) ] #线程名称
filename = [ "tmpfile_%d" % i for i in range(0, blocks) ] #线程对应的临时文件名称
tasks = []
for i in range(0,blocks):
task = MyPythonThread( threadname[i], url, filename[i], ranges[i] )
task.setDaemon( True ) #setDaemon当主线程结束时也结束子线程 需要在线程开始前调用
task.start()
tasks.append( task ) #线程列表
# time.sleep( 2 ) #睡眠2秒
startTime = time.time()
while islive(tasks):
downloaded = sum( [task.downloaded for task in tasks] ) #已下载文件大小
process = downloaded/float(size)*100
show = u'\rFilesize:%d Downloaded:%d Completed:%.2f%%' % (size, downloaded, process) #输出当前已下载的文件大小
sys.stdout.write(show)
sys.stdout.flush()
time.sleep( 0.5 )
endTime = time.time()
totalTime = endTime - startTime
print '总时间:',totalTime
#将所有的临时文件合并成完整文件
filehandle = open( output, 'wb+' ) #wb+以二进制读写模式打开
for i in filename:
f = open( i, 'rb' ) #rb以二进制读模式打开
data = f.read()
filehandle.write( data )
print i,'SIZE',len(data)
f.close()
try:
os.remove(i) #临时文件被读取之后 删除
pass
except:
pass
filehandle.close()
if __name__ == '__main__':
url = "http://down.51voa.com/201305/nigeria-fleming-bond.mp3"
output = 'D:/voa.mp3'
download( url, output, blocks=8, proxies={} )
JAVA多线程处理矩阵乘法
注意点:1.继承Runnable接口可以实现数据共享,因为只创建了一个对象,多个线程公用
2.子线程未结束时,主线程需等到
3.拿到需要处理的矩阵行,该值需要进行同步加锁操作
public class MyThreadTest implements Runnable {
int task = 0; //矩阵按行处理 task代表任务行
int threadCount = 0; //正在运行的线程数
int[][] a = {{1,2,3,4}, //指定相应的矩阵信息
{1,2,3,4},
{1,2,3,4},
{1,2,3,4}};
int[][] b = {{1,2,3,4},
{1,2,3,4},
{1,2,3,4},
{1,2,3,4}};
int[][] result = new int[a.length][b[0].length]; //result = a*b
//获得当前需要处理的行
synchronized int getTask(){
if(task < result.length){
return task++;
}
return -1;
}
@Override
public void run() {
int hang = 0; //第一个矩阵的行的个数
threadCount++;
while((hang = getTask()) != -1){
System.out.println(Thread.currentThread().getName()+"正在处理第"+(hang+1)+"行");
for(int i = 0;i<b[0].length;i++){ //第二个矩阵的列的个数
for(int j = 0;j<a[0].length;j++){ //第一个矩阵的列的个数
result[hang][i] += a[hang][j]*b[j][i];
}
}
}
threadCount--;
}
public static void main(String[] args) {
MyThreadTest t = new MyThreadTest();
//创建线程 不多于4个
for(int i = 0;i<4;i++){
if(t.task < t.result.length){
new Thread(t).start();
}
}
//当主线程下还有子线程还在运行 主线程休眠等待
while(t.threadCount != 0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//打印结果矩阵
for(int i = 0;i<t.result.length;i++){
for(int j = 0;j<t.result[0].length;j++){
System.out.print(t.result[i][j]+" ");
}
System.out.println();
}
}
}