From e4d3ea11f7921aa5ba82958c275f3850bb497e94 Mon Sep 17 00:00:00 2001 From: sdnb Date: Sat, 1 Apr 2017 00:16:22 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=A4=9A=E7=BA=BF=E7=A8=8B=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E7=BA=BF=E7=A8=8B=E6=B1=A0=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coding/week3/download/FileDownloader.java | 3 +- .../coding/week3/download1/DownloadTask.java | 50 +++++++ .../week3/download1/FileDownloader.java | 122 ++++++++++++++++++ .../week3/download1/api/Connection.java | 26 ++++ .../download1/api/ConnectionException.java | 10 ++ .../download1/api/ConnectionManager.java | 10 ++ .../week3/download1/api/DownloadListener.java | 5 + .../week3/download1/impl/ConnectionImpl.java | 55 ++++++++ .../download1/impl/ConnectionManagerImpl.java | 37 ++++++ .../com/coding/week3/FileDownloaderTest.java | 27 ++-- 10 files changed, 330 insertions(+), 15 deletions(-) create mode 100644 group24/494800949/src/main/java/com/coding/week3/download1/DownloadTask.java create mode 100644 group24/494800949/src/main/java/com/coding/week3/download1/FileDownloader.java create mode 100644 group24/494800949/src/main/java/com/coding/week3/download1/api/Connection.java create mode 100644 group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionException.java create mode 100644 group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionManager.java create mode 100644 group24/494800949/src/main/java/com/coding/week3/download1/api/DownloadListener.java create mode 100644 group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionImpl.java create mode 100644 group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionManagerImpl.java diff --git a/group24/494800949/src/main/java/com/coding/week3/download/FileDownloader.java b/group24/494800949/src/main/java/com/coding/week3/download/FileDownloader.java index 0e40bc38a8..75455935be 100644 --- a/group24/494800949/src/main/java/com/coding/week3/download/FileDownloader.java +++ b/group24/494800949/src/main/java/com/coding/week3/download/FileDownloader.java @@ -68,7 +68,6 @@ public void execute() throws IOException { lastLen = fileLength % nThread; perLenOfThread = (fileLength + (nThread - lastLen)) / nThread; } - //计算 //启动线程 for (int i = 0; i < nThread; i++) { @@ -87,7 +86,7 @@ public void execute() throws IOException { } catch (ConnectionException e) { e.printStackTrace(); - }finally{ + } finally{ if(conn != null){ conn.close(); } diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/DownloadTask.java b/group24/494800949/src/main/java/com/coding/week3/download1/DownloadTask.java new file mode 100644 index 0000000000..0c09657dc4 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/DownloadTask.java @@ -0,0 +1,50 @@ +package com.coding.week3.download1; + +import com.coding.week3.download.api.Connection; + +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by Administrator on 2017/3/31 0031. + */ +public class DownloadTask implements Runnable { + private static final int BUFF_SIZE = 1024; + Connection conn; + int startPos; + int endPos; + RandomAccessFile ras; + AtomicInteger downloadBytesCount; + + public DownloadTask(Connection conn, int startPos, int endPos, RandomAccessFile ras, AtomicInteger downloadBytesCount) { + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.ras = ras; + this.downloadBytesCount = downloadBytesCount; + } + + @Override + public void run() { + try { + InputStream is = conn.getInputStream(); + is.skip(startPos); + ras.seek(startPos); + byte[] bytes = new byte[BUFF_SIZE]; + int hasRead = 0; + int readTimes = (endPos - startPos) / BUFF_SIZE + 4; + for (int i = 0; i < readTimes; i++) { + hasRead = is.read(bytes ); + if (hasRead == -1) { + break; + } + ras.write(bytes, 0, hasRead); + downloadBytesCount.getAndAdd(hasRead); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/FileDownloader.java b/group24/494800949/src/main/java/com/coding/week3/download1/FileDownloader.java new file mode 100644 index 0000000000..81c7c87508 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/FileDownloader.java @@ -0,0 +1,122 @@ +package com.coding.week3.download1; + + +import com.coding.week3.download.api.Connection; +import com.coding.week3.download.api.ConnectionException; +import com.coding.week3.download.api.ConnectionManager; +import com.coding.week3.download.api.DownloadListener; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + String savePath; + + int nThread; + + int fileLength; + + AtomicInteger downloadBytesCount; + + public FileDownloader(String _url) { + this.url = _url; + } + + public FileDownloader(int nThread, String savePath, String url) { + this.nThread = nThread; + this.savePath = savePath; + this.url = url; + downloadBytesCount = new AtomicInteger(0); + } + + public void execute() throws IOException { + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + Connection conn = null; + try { + + //根据文件长度为每个线程分配下载字节数量 + conn = cm.open(this.url); + fileLength = conn.getContentLength(); + //已读字节数量 + + ExecutorService executorService = Executors.newFixedThreadPool(nThread); + int[][] allotSize = alloctSize(nThread, fileLength); + + for (int i = 0; i < nThread; i++) { + RandomAccessFile ras = new RandomAccessFile(savePath, "rw"); + executorService.execute(new DownloadTask(cm.open(url), allotSize[0][i], + allotSize[1][i], ras , downloadBytesCount)); + } + //关闭线程池 + executorService.shutdown(); + boolean isTermination ; + do { + System.out.println("已下载:"+(downloadBytesCount.get()/1024)+"K,百分比:"+ (downloadBytesCount.get()/ (fileLength/100))+"%" ); + //循环等待,直到线程全部关闭 + isTermination = executorService.awaitTermination(500, TimeUnit.MILLISECONDS); + } while (!isTermination); + + + } catch (ConnectionException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally{ + if(conn != null){ + conn.close(); + } + } + } + + private int[][] alloctSize(int nThread, int fileLength){ + int[][] allotSize = new int[2][nThread]; + int perLenOfTask = fileLength / nThread; + int lastLen = fileLength % nThread; + for (int i = 0; i < nThread; i++) { + int start = perLenOfTask * i; + int end = perLenOfTask * (i + 1) - 1; + if (i == nThread - 1) { + end += lastLen; + } + allotSize[0][i] = start; + allotSize[1][i] = end; + } + return allotSize; + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + + public DownloadListener getListener(){ + return this.listener; + } + +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/Connection.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/Connection.java new file mode 100644 index 0000000000..0811902dda --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/Connection.java @@ -0,0 +1,26 @@ +package com.coding.week3.download1.api; + +import java.io.IOException; +import java.io.InputStream; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + byte[] read(int startPos, int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + int getContentLength(); + + /** + * 关闭连接 + */ + void close(); + + InputStream getInputStream() throws IOException; +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionException.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionException.java new file mode 100644 index 0000000000..14f1291198 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionException.java @@ -0,0 +1,10 @@ +package com.coding.week3.download1.api; + +public class ConnectionException extends Exception { + public ConnectionException() { + } + + public ConnectionException(String message) { + super(message); + } +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionManager.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionManager.java new file mode 100644 index 0000000000..9674179b7a --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.coding.week3.download1.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + Connection open(String url) throws ConnectionException; +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/DownloadListener.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/DownloadListener.java new file mode 100644 index 0000000000..2195dd9be0 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.coding.week3.download1.api; + +public interface DownloadListener { + void notifyFinished(); +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionImpl.java b/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionImpl.java new file mode 100644 index 0000000000..3e8773ecca --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionImpl.java @@ -0,0 +1,55 @@ +package com.coding.week3.download1.impl; + +import com.coding.week3.download1.api.Connection; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; + + +public class ConnectionImpl implements Connection { + + private HttpURLConnection httpURLConnection; + + public ConnectionImpl() { + } + + public ConnectionImpl(HttpURLConnection httpURLConnection) { + this.httpURLConnection = httpURLConnection; + } + + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + if (startPos < 0 || endPos < 0 || endPos > getContentLength()) { + throw new IndexOutOfBoundsException(); + } + if (startPos >= endPos) { + throw new IllegalArgumentException(); + } + byte[] bytes = new byte[endPos - startPos + 1]; + + InputStream inputStream = httpURLConnection.getInputStream(); + BufferedInputStream bis = new BufferedInputStream(inputStream); + bis.read(bytes, startPos ,bytes.length-1); + return bytes; + } + + + @Override + public int getContentLength() { + return httpURLConnection.getContentLength(); + } + + @Override + public void close() { + httpURLConnection.disconnect(); + } + + @Override + public InputStream getInputStream() throws IOException { + return httpURLConnection.getInputStream(); + } + +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionManagerImpl.java b/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..3e65687879 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionManagerImpl.java @@ -0,0 +1,37 @@ +package com.coding.week3.download1.impl; + + +import com.coding.week3.download1.api.Connection; +import com.coding.week3.download1.api.ConnectionException; +import com.coding.week3.download1.api.ConnectionManager; + +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + try { + // 统一资源 + URL realurl = new URL(url); + // 连接类的父类,抽象类 + URLConnection urlConnection = realurl.openConnection(); + // http的连接类 + HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection; + // 设定请求的方法,默认是GET + httpURLConnection.setRequestMethod("GET"); + httpURLConnection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); + // 设置字符编码 + httpURLConnection.setRequestProperty("Charset", "UTF-8"); + // 打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)。 + httpURLConnection.connect(); + return new ConnectionImpl(httpURLConnection); + } catch (java.io.IOException e) { + e.printStackTrace(); + throw new ConnectionException(e.getMessage()); + } + } + +} diff --git a/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java b/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java index 5b423f145f..d0985c04d4 100644 --- a/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java +++ b/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java @@ -1,15 +1,16 @@ package com.coding.week3; -import com.coding.week3.download.FileDownloader; import com.coding.week3.download.api.ConnectionManager; import com.coding.week3.download.api.DownloadListener; import com.coding.week3.download.impl.ConnectionManagerImpl; +import com.coding.week3.download1.FileDownloader; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import java.io.*; +import java.io.File; +import java.io.IOException; public class FileDownloaderTest { @@ -49,17 +50,17 @@ public void notifyFinished() { downloader.execute(); - // 等待多线程下载程序执行完毕 - while (!downloadFinished) { - try { - System.out.println("还没有下载完成,休眠五秒"); - //休眠5秒 - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - System.out.println("下载完成!"); +// // 等待多线程下载程序执行完毕 +// while (!downloadFinished) { +// try { +// System.out.println("还没有下载完成,休眠五秒"); +// //休眠5秒 +// Thread.sleep(5000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// } +// System.out.println("下载完成!"); From 75cafe0bfe3cfa5e8e92bc838c5f755dafb82c7b Mon Sep 17 00:00:00 2001 From: sdnb Date: Tue, 4 Apr 2017 11:36:44 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=A4=9A=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E4=B8=8B=E8=BD=BD=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../week3/download/impl/ConnectionImpl.java | 17 +++- .../coding/week3/download1/DownloadTask.java | 77 +++++++++++++++---- .../week3/download1/FileDownloader.java | 75 ++++++++++++++---- .../download1/api/ConnectionException.java | 4 +- .../download1/api/ConnectionManager.java | 5 +- .../api/ConnectionRefuseException.java | 23 ++++++ .../download1/impl/ConnectionManagerImpl.java | 64 ++++++++++----- .../com/coding/week3/FileDownloaderTest.java | 12 +-- 8 files changed, 215 insertions(+), 62 deletions(-) create mode 100644 group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionRefuseException.java diff --git a/group24/494800949/src/main/java/com/coding/week3/download/impl/ConnectionImpl.java b/group24/494800949/src/main/java/com/coding/week3/download/impl/ConnectionImpl.java index fe9b0a9079..9617474677 100644 --- a/group24/494800949/src/main/java/com/coding/week3/download/impl/ConnectionImpl.java +++ b/group24/494800949/src/main/java/com/coding/week3/download/impl/ConnectionImpl.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; +import java.util.concurrent.TimeUnit; public class ConnectionImpl implements Connection { @@ -48,8 +49,20 @@ public void close() { } @Override - public InputStream getInputStream() throws IOException { - return httpURLConnection.getInputStream(); + public InputStream getInputStream() { + try { + return httpURLConnection.getInputStream(); + } catch (IOException e) { + for (int i = 0; i < 5; i++) { + try { + TimeUnit.SECONDS.sleep(10); + return httpURLConnection.getInputStream(); + } catch (IOException | InterruptedException e1) { + e1.printStackTrace(); + } + } + throw new RuntimeException(e); + } } } diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/DownloadTask.java b/group24/494800949/src/main/java/com/coding/week3/download1/DownloadTask.java index 0c09657dc4..2ef5729241 100644 --- a/group24/494800949/src/main/java/com/coding/week3/download1/DownloadTask.java +++ b/group24/494800949/src/main/java/com/coding/week3/download1/DownloadTask.java @@ -1,10 +1,10 @@ package com.coding.week3.download1; -import com.coding.week3.download.api.Connection; +import com.coding.week3.download1.api.Connection; +import com.coding.week3.download1.api.ConnectionManager; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; +import java.io.*; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** @@ -12,39 +12,82 @@ */ public class DownloadTask implements Runnable { private static final int BUFF_SIZE = 1024; - Connection conn; - int startPos; - int endPos; - RandomAccessFile ras; - AtomicInteger downloadBytesCount; - - public DownloadTask(Connection conn, int startPos, int endPos, RandomAccessFile ras, AtomicInteger downloadBytesCount) { - this.conn = conn; + ConnectionManager connectionManager; + int startPos; + int endPos; + RandomAccessFile ras; + AtomicInteger totalDownloadBytesCount; + AtomicInteger eachThreadDownloadBytesCount; + String url; + + public DownloadTask(String url, ConnectionManager connectionManager, int startPos, int endPos, RandomAccessFile ras, AtomicInteger totalDownloadBytesCount) { + this.url = url; + this.connectionManager = connectionManager; this.startPos = startPos; this.endPos = endPos; this.ras = ras; - this.downloadBytesCount = downloadBytesCount; + this.totalDownloadBytesCount = totalDownloadBytesCount; + this.eachThreadDownloadBytesCount = new AtomicInteger(0); } @Override public void run() { + Connection conn = null; + InputStream is = null; try { - InputStream is = conn.getInputStream(); + conn = connectionManager.open(url); + is = getInputStream(conn); is.skip(startPos); ras.seek(startPos); byte[] bytes = new byte[BUFF_SIZE]; - int hasRead = 0; + int hasRead; int readTimes = (endPos - startPos) / BUFF_SIZE + 4; for (int i = 0; i < readTimes; i++) { - hasRead = is.read(bytes ); + hasRead = is.read(bytes); if (hasRead == -1) { break; } ras.write(bytes, 0, hasRead); - downloadBytesCount.getAndAdd(hasRead); + totalDownloadBytesCount.getAndAdd(hasRead); + eachThreadDownloadBytesCount.getAndAdd(hasRead); } + } catch (IOException e) { e.printStackTrace(); } } + + + private InputStream getInputStream(Connection connection){ + Connection conn = null; + InputStream is = null; + try { + conn = connectionManager.open(url); + is = conn.getInputStream(); + return is; + } catch (IOException e) { + for (int i = 0; i < 5; i++) { + try { + TimeUnit.SECONDS.sleep(5); + conn = connectionManager.open(url); + is = conn.getInputStream(); + is.skip(startPos); + break; + } catch (InterruptedException e1) { + e1.printStackTrace(); + } catch (IOException e1) { + System.out.println(e1.getMessage()); + } + } + throw new RuntimeException("连接超时", e); + } + + } + + + + + public int getEachThreadDownloadBytesCount() { + return eachThreadDownloadBytesCount.get(); + } } diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/FileDownloader.java b/group24/494800949/src/main/java/com/coding/week3/download1/FileDownloader.java index 81c7c87508..72b11c120e 100644 --- a/group24/494800949/src/main/java/com/coding/week3/download1/FileDownloader.java +++ b/group24/494800949/src/main/java/com/coding/week3/download1/FileDownloader.java @@ -1,13 +1,12 @@ package com.coding.week3.download1; -import com.coding.week3.download.api.Connection; -import com.coding.week3.download.api.ConnectionException; -import com.coding.week3.download.api.ConnectionManager; -import com.coding.week3.download.api.DownloadListener; +import com.coding.week3.download1.api.Connection; +import com.coding.week3.download1.api.ConnectionException; +import com.coding.week3.download1.api.ConnectionManager; +import com.coding.week3.download1.api.DownloadListener; -import java.io.IOException; -import java.io.RandomAccessFile; +import java.io.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -55,36 +54,39 @@ public void execute() throws IOException { // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 Connection conn = null; + DownloadTask[] downloadTasks = new DownloadTask[nThread]; try { //根据文件长度为每个线程分配下载字节数量 conn = cm.open(this.url); fileLength = conn.getContentLength(); //已读字节数量 - ExecutorService executorService = Executors.newFixedThreadPool(nThread); - int[][] allotSize = alloctSize(nThread, fileLength); - +// int[][] allotSize = alloctSize(nThread, fileLength); + int[][] allotSize = readPos(nThread, fileLength); for (int i = 0; i < nThread; i++) { RandomAccessFile ras = new RandomAccessFile(savePath, "rw"); - executorService.execute(new DownloadTask(cm.open(url), allotSize[0][i], - allotSize[1][i], ras , downloadBytesCount)); + downloadTasks[i] = new DownloadTask(url, cm, allotSize[0][i], + allotSize[1][i], ras , downloadBytesCount); + executorService.execute(downloadTasks[i]); } //关闭线程池 executorService.shutdown(); boolean isTermination ; do { - System.out.println("已下载:"+(downloadBytesCount.get()/1024)+"K,百分比:"+ (downloadBytesCount.get()/ (fileLength/100))+"%" ); - //循环等待,直到线程全部关闭 isTermination = executorService.awaitTermination(500, TimeUnit.MILLISECONDS); + if (fileLength > 0) + System.out.println("已下载:"+(downloadBytesCount.get()/1024)+"K,百分比:"+ (downloadBytesCount.get()/ (fileLength/100))+"%" ); + //循环等待,直到线程全部关闭 } while (!isTermination); - + System.out.println(111111); } catch (ConnectionException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } finally{ + writePos(downloadTasks); if(conn != null){ conn.close(); } @@ -118,5 +120,48 @@ public void setConnectionManager(ConnectionManager ucm){ public DownloadListener getListener(){ return this.listener; } - + + private void writePos(DownloadTask[] tasks){ + File file = new File(""); + File posFile = new File(file.getAbsolutePath()+"/tempPos"); + RandomAccessFile ras = null; + try { + ras = new RandomAccessFile(posFile, "rw"); + if (!posFile.exists()) { + posFile.createNewFile(); + } + for (int i = 0; i < tasks.length; i++) { + ras.writeInt(tasks[i].getEachThreadDownloadBytesCount()); + ras.writeInt(tasks[i].endPos); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private int[][] readPos(int nThread, int fileLength){ + File file = new File(""); + File posFile = new File(file.getAbsolutePath()+"/tempPos"); + if (!posFile.exists()) { + return alloctSize(nThread, fileLength); + } + RandomAccessFile ras = null; + int[][] pos = new int[2][nThread]; + try { + ras = new RandomAccessFile(posFile, "r"); + ras.seek(0); + for (int i = 0; i < nThread; i++) { + pos[0][i] = ras.readInt(); + pos[1][i] = ras.readInt(); + } + return pos; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return pos; + } } diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionException.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionException.java index 14f1291198..b1d8dddc42 100644 --- a/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionException.java +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionException.java @@ -1,6 +1,8 @@ package com.coding.week3.download1.api; -public class ConnectionException extends Exception { +import java.io.IOException; + +public class ConnectionException extends IOException { public ConnectionException() { } diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionManager.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionManager.java index 9674179b7a..f9ab90bc59 100644 --- a/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionManager.java +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionManager.java @@ -1,10 +1,13 @@ package com.coding.week3.download1.api; +import java.io.IOException; +import java.net.MalformedURLException; + public interface ConnectionManager { /** * 给定一个url , 打开一个连接 * @param url * @return */ - Connection open(String url) throws ConnectionException; + Connection open(String url) throws IOException; } diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionRefuseException.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionRefuseException.java new file mode 100644 index 0000000000..653d9520a4 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionRefuseException.java @@ -0,0 +1,23 @@ +package com.coding.week3.download1.api; + +import java.io.IOException; + +/** + * Created by Administrator on 2017/4/2 0002. + */ +public class ConnectionRefuseException extends IOException{ + public ConnectionRefuseException() { + } + + public ConnectionRefuseException(String message) { + super(message); + } + + public ConnectionRefuseException(String message, Throwable cause) { + super(message, cause); + } + + public ConnectionRefuseException(Throwable cause) { + super(cause); + } +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionManagerImpl.java b/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionManagerImpl.java index 3e65687879..927fc30d90 100644 --- a/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionManagerImpl.java +++ b/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionManagerImpl.java @@ -2,9 +2,9 @@ import com.coding.week3.download1.api.Connection; -import com.coding.week3.download1.api.ConnectionException; import com.coding.week3.download1.api.ConnectionManager; +import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; @@ -12,26 +12,48 @@ public class ConnectionManagerImpl implements ConnectionManager { @Override - public Connection open(String url) throws ConnectionException { - try { - // 统一资源 - URL realurl = new URL(url); - // 连接类的父类,抽象类 - URLConnection urlConnection = realurl.openConnection(); - // http的连接类 - HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection; - // 设定请求的方法,默认是GET - httpURLConnection.setRequestMethod("GET"); - httpURLConnection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); - // 设置字符编码 - httpURLConnection.setRequestProperty("Charset", "UTF-8"); - // 打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)。 - httpURLConnection.connect(); - return new ConnectionImpl(httpURLConnection); - } catch (java.io.IOException e) { - e.printStackTrace(); - throw new ConnectionException(e.getMessage()); - } + public Connection open(String url) throws IOException { + HttpURLConnection httpURLConnection = null; + // 统一资源 + URL realurl = new URL(url); + // 连接类的父类,抽象类 + URLConnection urlConnection = realurl.openConnection(); + // http的连接类 + httpURLConnection = (HttpURLConnection) urlConnection; + //设置属性 + setHeader(httpURLConnection); + + //设置连接超时时间 + setWaitTime(httpURLConnection); + + // 打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)。 + httpURLConnection.connect(); + return new ConnectionImpl(httpURLConnection); + } + + private void setHeader(HttpURLConnection con){ + con.setRequestProperty( + "User-Agent", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 Ubuntu/8.04 (hardy) Firefox/3.0.3"); + con.setRequestProperty("Accept-Language", "en-us,en;q=0.7,zh-cn;q=0.3"); + con.setRequestProperty("Accept-Encoding", "aa"); + con.setRequestProperty("Accept-Charset", + "ISO-8859-1,utf-8;q=0.7,*;q=0.7"); + con.setRequestProperty("Keep-Alive", "300"); + con.setRequestProperty("Connection", "keep-alive"); + con.setRequestProperty("If-Modified-Since", + "Fri, 02 Jan 2009 17:00:05 GMT"); + con.setRequestProperty("If-None-Match", "\"1261d8-4290-df64d224\""); + con.setRequestProperty("Cache-Control", "max-age=0"); + con.setRequestProperty("Referer", + "http://www.skycn.com/soft/14857.html"); + } + + + private void setWaitTime(HttpURLConnection con) { + //防止网络阻塞,设置指定的超时时间;单位都是ms。超过指定时间,就会抛出异常 + con.setConnectTimeout(10000); //连接超时设置 + con.setReadTimeout(10000); //读取超时设置 } } diff --git a/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java b/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java index d0985c04d4..524e3aaabb 100644 --- a/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java +++ b/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java @@ -1,8 +1,8 @@ package com.coding.week3; -import com.coding.week3.download.api.ConnectionManager; -import com.coding.week3.download.api.DownloadListener; -import com.coding.week3.download.impl.ConnectionManagerImpl; +import com.coding.week3.download1.api.ConnectionManager; +import com.coding.week3.download1.api.DownloadListener; +import com.coding.week3.download1.impl.ConnectionManagerImpl; import com.coding.week3.download1.FileDownloader; import org.junit.After; import org.junit.Assert; @@ -28,10 +28,12 @@ public void tearDown() throws Exception { @Test public void testDownload() throws IOException { -// String url = "http://101.95.48.97:8005/res/upload/interface/apptutorials/manualstypeico/6f83ce8f-0da5-49b3-bac8-fd5fc67d2725.png"; + String url = "http://101.95.48.97:8005/res/upload/interface/apptutorials/manualstypeico/6f83ce8f-0da5-49b3-bac8-fd5fc67d2725.png"; // String url = "http://download.oracle.com/otn-pub/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-linux-arm32-vfp-hflt.tar.gz"; // String url = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1490808670106&di=48aa6fb7af641f0cb6f9e19120b60c7c&imgtype=0&src=http%3A%2F%2Fwww.ntjoy.com%2Fliv_loadfile%2Fhealth%2Fdzcs%2Fnvr%2Ffold1%2F1360480639_97304600.jpg"; - String url = "https://download.jetbrains.com/idea/ideaIU-2017.1.exe"; +// String url = "https://download.jetbrains.com/idea/ideaIU-2017.1.exe"; +// String url = "https://nodejs.org/dist/v6.10.1/node-v6.10.1-win-x64.zip"; +// String url = "http://download.oracle.com/otn-pub/java/jdk/8u121-b13-demos/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-windows-x64-demos.zip"; String path = new File("").getAbsolutePath(); String filename = url.substring(url.lastIndexOf("/"), url.length()); filename = path +File.separator + filename; From 90728fee103a3a0d4a9bb58d009f1c7c52272cd0 Mon Sep 17 00:00:00 2001 From: sdnb Date: Tue, 4 Apr 2017 23:26:35 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E7=AC=AC=E5=9B=9B=E5=91=A8=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A-jvm=E5=8F=8ALRU?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jvm/loader/ClassFileLoader.java | 59 +++++++ .../coding/week4/linklist/LRUPageFrame.java | 157 ++++++++++++++++++ .../com/coding/week4/linklist/LinkedList.java | 126 ++++++++++++++ .../mini_jvm/test/ClassFileloaderTest.java | 92 ++++++++++ .../com/coding/mini_jvm/test/EmployeeV1.java | 28 ++++ .../com/coding/week4/LRUPageFrameTest.java | 32 ++++ 6 files changed, 494 insertions(+) create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java create mode 100644 group24/494800949/src/main/java/com/coding/week4/linklist/LRUPageFrame.java create mode 100644 group24/494800949/src/main/java/com/coding/week4/linklist/LinkedList.java create mode 100644 group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java create mode 100644 group24/494800949/src/test/java/com/coding/mini_jvm/test/EmployeeV1.java create mode 100644 group24/494800949/src/test/java/com/coding/week4/LRUPageFrameTest.java diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..1ca7cc8ece --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,59 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.loader; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; + + + +public class ClassFileLoader { + + private static final String CLASS_FILE_SUFFIX = ".class"; + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + String classPath = getClassPath(); + String[] paths = classPath.split(File.pathSeparator); + className = className.replaceAll("\\.", "\\"+File.separator) ; + for (String path : paths) { + String filename = path + File.separator + className + CLASS_FILE_SUFFIX; + File file = new File(filename); + if (file.exists()) { + try { + FileInputStream fis = new FileInputStream(file); + BufferedInputStream bis = new BufferedInputStream(fis); + byte[] data = new byte[bis.available()]; + bis.read(data); + return data; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + } + + + public void addClassPath(String path) { + clzPaths.add(path); + } + + + + public String getClassPath(){ + StringBuffer sb = new StringBuffer(); + for (String path : clzPaths) { + sb.append(path); + sb.append(";"); + } + String path = sb.toString(); + return path.substring(0, path.lastIndexOf(";")); + } + + + + + +} diff --git a/group24/494800949/src/main/java/com/coding/week4/linklist/LRUPageFrame.java b/group24/494800949/src/main/java/com/coding/week4/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..bd31cd26f3 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week4/linklist/LRUPageFrame.java @@ -0,0 +1,157 @@ +package com.coding.week4.linklist; + +/** + * 用双向链表实现LRU算法 + * @author liuxin + * + */ +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + + public Node(Node prev, int pageNum, Node next) { + this.prev = prev; + this.next = next; + this.pageNum = pageNum; + } + } + + private int capacity; + private int size; + + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param + * @return + */ + public void access(int pageNum) { + if (!isFull()) { + addFirst(pageNum); + } else { + if (contains(pageNum)) { + removePage(pageNum); + addFirst(pageNum); + } else { + removeLast(); + addFirst(pageNum); + } + } + } + + public boolean contains(int pageNum) { + Node node = first; + if (first == null) + return false; + do { + if (pageNum == node.pageNum) + return true; + node = node.next; + } while (node != null ); + return false; + } + + + public void addFirst(int pageNum){ + Node node = new Node(null, pageNum, null); + if (first == null) { + first = node; + last = node; + } else { + Node oldFirst = first; + first = node; + node.next = oldFirst; + oldFirst.prev = node; + } + size++; + } + + + public boolean isFull () { + return size == capacity; + } + + + public void addLast(int pageNum) { + Node oldLast = last; + Node node = new Node(oldLast, pageNum, null); + oldLast.next = node; + last = node; + size++; + } + + + public int removeLast(){ + Node oldLast = last; + last = oldLast.prev; + last.next = null; + size--; + return oldLast.pageNum; + } + + + public void removePage(int pageNum){ + Node node = first; + if (first == null) { + return; + } + do { + if (node.pageNum == pageNum) { + if (node == first) { + removeFirst(); + } else if (node == last) { + removeLast(); + } else { + Node pre = node.prev; + Node nex = node.next; + pre.next = nex; + nex.prev = pre; + size--; + } + return; + } + node = node.next; + } while (node != null); + } + + private void removeFirst() { + Node node = first; + first = node.next; + first.prev = null; + node.next = null; + size--; + } + + + public String toString(){ + StringBuilder buffer = new StringBuilder(); + Node node = first; + while(node != null){ + buffer.append(node.pageNum); + + node = node.next; + if(node != null){ + buffer.append(","); + } + } + return buffer.toString(); + } + +} diff --git a/group24/494800949/src/main/java/com/coding/week4/linklist/LinkedList.java b/group24/494800949/src/main/java/com/coding/week4/linklist/LinkedList.java new file mode 100644 index 0000000000..1285ed8fa1 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week4/linklist/LinkedList.java @@ -0,0 +1,126 @@ +package com.coding.week4.linklist; + + +import com.coding.weak1.Iterator; +import com.coding.weak1.List; + +public class LinkedList implements List { + + private Node head; + + public void add(Object o){ + + } + public void add(int index , Object o){ + + } + public Object get(int index){ + return null; + } + public Object remove(int index){ + return null; + } + + public int size(){ + return -1; + } + + public void addFirst(Object o){ + + } + public void addLast(Object o){ + + } + public Object removeFirst(){ + return null; + } + public Object removeLast(){ + return null; + } + public Iterator iterator(){ + return null; + } + + + private static class Node{ + Object data; + Node next; + + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + return null; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + return null; + } +} diff --git a/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java b/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..830d0b7efe --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java @@ -0,0 +1,92 @@ +package com.coding.mini_jvm.test; + +import com.coding.mini_jvm.src.com.coderising.jvm.loader.ClassFileLoader; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + + + + +public class ClassFileloaderTest { + + + static String path1 = "H:\\sourceCode\\coding2017\\group24\\494800949\\build\\classes\\test"; + static String path2 = "C:\temp"; + + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1+";"+path2,clzPath); + + } + + @Test + public void testClassFileLength() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coding.mini_jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1058, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coding.mini_jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + + + + + + private String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i