Java 如何实现多线程下载操作

本文以tomact 服务器 作介绍:

 一:建一个 webproject,在Webroot 目录新建一个文件夹 用来存放下载的资源。

二:建立需要的包和类:

    创建包:

    在src下新建一个包用来存放下载的java类。

    命名规范:

    命名规范为公司名+java类的属性

     如:bean   包 用来存放 实体  dao 包用来存放接口 util 存放工具 imp 包存放 接口的实现类; junit 包用来存放测试类。

 

    由于本人以下代码只做讲解用,部分名称不规范请谅解;


三:设置加载下载的资源:

 在 webroot目录下新建资源包,存放下载内容,本例资源名称为mg.avi;

Java 如何实现多线程下载操作_第1张图片

四:代码介绍:


1.      下载的界面:

package download.util;

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;

public class DownloadJFrame extends JFrame {

	// 声明组件
	private JLabel downloadJLabel;
	private JTextField downLoadJTextField;
	private JButton downJButton;
	
	private JLabel threadJLabel;
	private JTextField threadJTextField;
	// 声明 滚动条

	private JProgressBar downloadJProgressBar;

	public DownloadJFrame() {

		// 设置标题
		this.setTitle("下载工具");
		this.setSize(400, 300);
		// 设置居中显示
		this.setLocationRelativeTo(null);
		// 设置关闭时退出程序
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		// 获取面板的对象
		Container c = this.getContentPane();

		// 将面板的布局设置为空
		c.setLayout(null);

		// 实例化组件

		downloadJLabel = new JLabel("下载地址:");
		downLoadJTextField = new JTextField(
				"http://localhost:8080/demo/res/mg.avi");
		downJButton = new JButton("下载");
		threadJLabel= new JLabel("线程数量");
		threadJTextField=new JTextField("3");

		downloadJProgressBar= new JProgressBar();
		// 设置组件的位置
		downloadJLabel.setBounds(20, 50, 70, 30);
		downLoadJTextField.setBounds(95, 50, 260, 30);
		threadJLabel.setBounds(20, 85, 70, 30);
		threadJTextField.setBounds(95, 85, 260, 30);
		downloadJProgressBar.setBounds(10, 130, 360, 10);
		downJButton.setBounds(170, 150, 80, 30);
		// 将组建添加到面板上
		c.add(downloadJLabel);
		c.add(downLoadJTextField);
		c.add(downJButton);
		c.add(downloadJProgressBar);
		c.add(threadJLabel);
		c.add(threadJTextField);
		// 添加点击事件
		downJButton.addActionListener(new MyactionListener());

		this.setVisible(true);
	}

	public static void main(String[] args) {
		new DownloadJFrame();
	}

	//声明一个内部类实现ActionListener  
	class MyactionListener implements ActionListener {

		// 声明一个随机的文件
		private RandomAccessFile accessFile;

		@Override
		public void actionPerformed(ActionEvent e) {
			// 设置按钮不可用
			downJButton.setEnabled(false);
			// 获取下载的地址
			final String path = downLoadJTextField.getText();

			// 在指定的目录 创建 指定大小的文件 和类型
			try {
				// 根据路径创建url对象
				URL url = new URL(path);
				// 打开连接
				HttpURLConnection httpURLConnection = (HttpURLConnection) url
						.openConnection();

				// 设置请求头的方式
				httpURLConnection.setRequestMethod("GET");
				// 设置连接的超时时间
				httpURLConnection.setConnectTimeout(5000);
				// 设置请求的头像
				httpURLConnection
						.setRequestProperty("User-Agent",
								"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0");

				// System.out.println(httpURLConnection.getResponseCode());
				// 获取下载文件的饿大小
				int size = httpURLConnection.getContentLength();
				// 根据下载的文件名称设置本地保存的文件
				File file = new File("F:"
						+ path.substring(path.lastIndexOf("/")));
				// 根据文件创建出RnadomAccessFile 对象
				accessFile = new RandomAccessFile(file, "rw");
				// 设置文件的大小
				accessFile.setLength(size);
				// 关闭流
				accessFile.close();
				// 断开连接
				httpURLConnection.disconnect();

				String num= threadJTextField.getText();
				int threadNum =Integer.parseInt(num);
				
				System.out.println(threadNum);
				// 定义线程的数量
		
				for (int i = 1; i <= threadNum; i++) {
					// 计算出每个线程下载的平均量(daxiao )
					int blockSize = size / threadNum;
					// 计算出每个线程开始下载的位置
					int startSize = (i - 1) * blockSize;

					// 计算出每个线程下载的结束的位置
					int endSize = i * blockSize - 1;
					if (i == threadNum) {
						if (endSize < size) {
							endSize = size;
						}
					}
					// 文件随机读取的对象
					RandomAccessFile threadFile = new RandomAccessFile(file,
							"rw");

					// 创建线程下载
					new DownLoadThread(path, startSize, endSize, threadFile,downloadJProgressBar)
							.start();

				}

			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

		}

	}

}



2.      所需线程的封装类:

package download.util;

import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.swing.JProgressBar;

import org.xml.sax.InputSource;

public class DownLoadThread extends Thread {

	// 下载的路径
	private String path;
	private int startSize;
	private int endSize;
	// 随机读取文件的对象
	private RandomAccessFile threadFile;

	//声明 滚动条
	
		private JProgressBar downloadJProgressBar;
	// 实例化
		public DownLoadThread(String path, int startSize, int endSize,
				RandomAccessFile threadFile, JProgressBar downloadJProgressBar) {
			super();
			this.path = path;
			this.startSize = startSize;
			this.endSize = endSize;
			this.threadFile = threadFile;
			this.downloadJProgressBar = downloadJProgressBar;
		}



	@Override
	public void run() {
		// 根据路径创建URl对象
		try {

			// 获取路径
			URL url = new URL(path);
			// 打开连接
			HttpURLConnection httpURLConnection = (HttpURLConnection) url
					.openConnection();

			// 设置请求的方式
			httpURLConnection.setRequestMethod("GET");
			// 设置连接的超时时间
			httpURLConnection.setConnectTimeout(5000);
			// 设置请求的头信息
			httpURLConnection
					.setRequestProperty("User-Agent",
							"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0");

			// 测试 用 输出
			System.out.println(Thread.currentThread().getName() + "从----开始"
					+ startSize + "下载。。。到----" + endSize + "结束");
			//设置你读取的range 的范围
			httpURLConnection.setRequestProperty("Range", "bytes="+startSize+"-"+endSize);
			
			
			//获取输入流
			InputStream is= httpURLConnection.getInputStream();
			//设置文件开始写入的位置
			threadFile.seek(startSize);
			//缓冲区
			byte buffer[]= new byte[1024];
			//读取的长度
			int len=0;
			while((len=is.read(buffer))!=-1){
				//获取进度条的值
				int total=downloadJProgressBar.getValue();
				//改变进度条
				total+=len;
				downloadJProgressBar.setValue(total);
				//写入
				threadFile.write(buffer, 0, len);
				
			}
			//释放资源
			is.close();
			threadFile.close();
			httpURLConnection.disconnect();
		} catch (Exception e) {
			
			e.printStackTrace();
		}

	}
	

}


五:将工程发布到web服务器上,开启服务器;

Java 如何实现多线程下载操作_第2张图片Java 如何实现多线程下载操作_第3张图片


六:运行效果:

 只要下载地址服务器上存在,线程数可自定义,即可完成下载。
Java 如何实现多线程下载操作_第4张图片

你可能感兴趣的:(thread,多线程,windows,web服务器,实例)