多线程--Python下载(支持断点续传) & Java多线程计算矩阵乘法

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();
		}
	}

}

      

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值