多线程下载,有返回值

多线程实现下载文件带返回值

这一篇说的是多线程CallableCallable 实现的线程是可以实现有返回值的。
下面将全面啊讲述使用多线程下载网页图片的一个小案例

  1. 先创建一个StartThreadCallable 线程类 实现 Callable
    参数 allUrl:网络地址多个用逗号隔开,可以根据你的需求进行修改
    filepat:本地保存的路径地址 例:D:/img
    taskNumber:此方法是在那个线程下运行的
		@SuppressWarnings("all")
		public class StartThreadCallable implements Callable<Object>{
			private String allUrl;  
			private String filepath;
			private int taskNumber; //第几个线程
			
			public StartThreadCallable(String allUrl,String filepath,int taskNumber) {
				this.allUrl=allUrl;
				this.filepath=filepath;
				this.taskNumber=taskNumber;
			}
			
			
			public Object call() throws Exception {
				 System.out.println("callable 带返回值多线程  启动   ---参数  allUrl--> "+ allUrl+"--filepath--"+filepath );  
				 
				 String retMsg="";
				 String stringArray[]= this.allUrl.split(",");
			     for (int i = 0; i < stringArray.length; i++) {
			    	 System.err.println("多线程执行方法"+taskNumber);
			    	 
			    	 if(retMsg.length()>0){
			    		 retMsg+=",";
			    	 } 
			    	 retMsg+=download(stringArray[i],filepath);
				 }
			    
			    System.out.println("线程返回内容-->"+retMsg);
				return retMsg;
			}
			
			
			/**
			 * 
			 * @param downUrl
			 * @param filepath
			 * @return
			 */
			private String download(String downUrl ,String filepath){
				String fileName="";
				System.out.println();
				
				URL url=null;
				try {
					if(downUrl.length()>0){
						fileName=taskNumber+"-"+downUrl.substring(downUrl.lastIndexOf("/")+1);
						//网络图片路径下载
						url = new URL(downUrl);
						DataInputStream dataInputStream = new DataInputStream(url.openStream());
						
						//本地路径图片路径
						filepath =filepath+"/"+fileName;
						
						//输出流
						FileOutputStream fileOutputStream = new FileOutputStream(new File(filepath));
			            ByteArrayOutputStream output = new ByteArrayOutputStream();
			
			            byte[] buffer = new byte[1024];
			            int length;
			
			            while ((length = dataInputStream.read(buffer)) > 0) {
			                output.write(buffer, 0, length);
			            }
			            byte[] context=output.toByteArray();
			            fileOutputStream.write(output.toByteArray());
			            
			            dataInputStream.close();
			            fileOutputStream.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
					System.out.println("下载图片出错");
					fileName="";
				}
				
				return fileName;
			}
			
		
		}
  1. 创建CreatThreadCallable 类,用来实现创建多个线程使用
    参数allUrl:是一个数组,我是用的数组的长度来创建的线程的长度,一般不建议,如果数组长度过大,会造高并发问题。
    filePath 本地文件路径
    taskSize 要创建的线程数,下面会由数组长度覆盖这个值(不建议这样写)
    注意:不要在创建多线程的for 循环中 做输出语句以及对线程返回值的处理,这样会把多线程变成单线程,这样多线程就毫无意义啦,可以通过 list.add(f); 直接把返回值存到 list中在下面再写一个for循环进行逻辑的操作,这样就避免啦多线程变单线程。
public class CreatThreadCallable {
	
	public String createThreadCallable(String[] allUrl,String filePath,int taskSize) {
		
		String stringArray="";
		try {
			System.err.println("----进入线程  创建方法----");  
			
			//可以给根据 数组的长度 来 创建线程数量 也可以 写固定值
			taskSize=allUrl.length;
		    // 创建一个线程池  taskSize 线程数量
		    ExecutorService pool = Executors.newFixedThreadPool(taskSize);  
		    // 创建多个有返回值的任务  
		    List<Future> list = new ArrayList<Future>();
		    for (int i = 0; i < taskSize; i++) {
			     Callable c = new StartThreadCallable(allUrl[i],filePath,i);  
			     // 执行任务并获取Future对象  
			     Future f = pool.submit(c);
			     list.add(f); 
		    }  
		    // 执行完线程    关闭线程池
		    pool.shutdown();  
		    
		    
		    // 获取所有并发任务的运行结果  
	       for (Future f : list) {  
	    	   // 从Future对象上获取任务的返回值,并输出到控制台  
		       //System.out.println(">>>" + f.get().toString()); 
		        if(stringArray.length()>0){
		        	stringArray+=",";	
		        }
		        stringArray+=f.get().toString();
	       }
		} catch (Exception e) {
			e.printStackTrace();
		}
	    
		return stringArray;
	    
	}
}
  1. 创建实体类进行测试
    我这就直接用数组放图片地址,多个地址用逗号隔开。
public class text {
	public static void main(String[] args) {
		try {
			CreatThreadCallable creatThreadCallable=new CreatThreadCallable();
			
			String[] allUrl=new String[3];
			
			allUrl[0]="http://img.tupianzj.com/uploads/allimg/140418/3-14041Q43F40-L.jpg,http://img.tupianzj.com/uploads/allimg/140319/4-1403191055450-L.jpg,http://img.tupianzj.com/uploads/allimg/131120/3-1311200954320-L.jpg";
			allUrl[1]="http://img.tupianzj.com/uploads/allimg/130802/4-130P21036010-L.jpg";
			allUrl[2]="http://img.tupianzj.com/uploads/allimg/180523/9-1P5231000080-L.jpg,http://img.tupianzj.com/uploads/allimg/140604/3-1406041414480-L.jpg,http://img.tupianzj.com/uploads/allimg/171017/9-1G01G15T00-L.jpg,http://img.tupianzj.com/uploads/allimg/170805/9-1FP51IA80-L.jpg,http://img.tupianzj.com/uploads/allimg/180522/9-1P5221631200-L.jpg,http://img.tupianzj.com/uploads/allimg/180331/9-1P3311131060-L.jpg,http://img.tupianzj.com/uploads/allimg/160724/9-160H41A4550-L.jpg,http://img.tupianzj.com/uploads/allimg/150317/7-15031G511460-L.jpg,http://img.tupianzj.com/uploads/allimg/180202/9-1P2021AS60-L.jpg,http://img.tupianzj.com/uploads/allimg/180202/9-1P2021A5070-L.jpg";
			
			String stringArray=creatThreadCallable.createThreadCallable(allUrl,"D:/临时/threadimg/",3);
			
			String[] strA=stringArray.split(",");
			for (int i = 0; i < strA.length; i++) {
				System.out.println("main----"+strA[i]);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}

这就是简单的使用多线程下载文件,并且会有返回值的全部操作。具体应用的时候需要加上一些报错的处理等操作,
想要免费学习dubbo分布式开发,以及redis共享session等学习资料可以通过微信进行扫码获取
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值