From bbd2cd22d50a9d18048c76c14095529b893e6a24 Mon Sep 17 00:00:00 2001 From: guoqixuan <1016908591@qq.com> Date: Tue, 28 Mar 2017 21:13:11 +0800 Subject: [PATCH] 1016908591week03 --- .../coderising/download/DownloadThread.java | 49 +++ .../coderising/download/FileDownloader.java | 142 +++++++++ .../download/FileDownloaderTest.java | 59 ++++ .../coderising/download/api/Connection.java | 23 ++ .../download/api/ConnectionException.java | 5 + .../download/api/ConnectionManager.java | 10 + .../download/api/DownloadListener.java | 5 + .../download/impl/ConnectionImpl.java | 83 +++++ .../download/impl/ConnectionManagerImpl.java | 14 + .../download/test/ConnectionTest.java | 57 ++++ .../download/test/FileDownloaderTest.java | 66 ++++ .../src/com/coding/basic/LinkedList.java | 283 ++++++++++++++++++ 12 files changed, 796 insertions(+) create mode 100644 group27/1016908591/week03/src/com/coderising/download/DownloadThread.java create mode 100644 group27/1016908591/week03/src/com/coderising/download/FileDownloader.java create mode 100644 group27/1016908591/week03/src/com/coderising/download/FileDownloaderTest.java create mode 100644 group27/1016908591/week03/src/com/coderising/download/api/Connection.java create mode 100644 group27/1016908591/week03/src/com/coderising/download/api/ConnectionException.java create mode 100644 group27/1016908591/week03/src/com/coderising/download/api/ConnectionManager.java create mode 100644 group27/1016908591/week03/src/com/coderising/download/api/DownloadListener.java create mode 100644 group27/1016908591/week03/src/com/coderising/download/impl/ConnectionImpl.java create mode 100644 group27/1016908591/week03/src/com/coderising/download/impl/ConnectionManagerImpl.java create mode 100644 group27/1016908591/week03/src/com/coderising/download/test/ConnectionTest.java create mode 100644 group27/1016908591/week03/src/com/coderising/download/test/FileDownloaderTest.java create mode 100644 group27/1016908591/week03/src/com/coding/basic/LinkedList.java diff --git a/group27/1016908591/week03/src/com/coderising/download/DownloadThread.java b/group27/1016908591/week03/src/com/coderising/download/DownloadThread.java new file mode 100644 index 0000000000..c357c245c3 --- /dev/null +++ b/group27/1016908591/week03/src/com/coderising/download/DownloadThread.java @@ -0,0 +1,49 @@ +package com.coderising.download; + +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +import com.coderising.download.api.Connection; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + CyclicBarrier barrier; + String localFile; + +public DownloadThread( Connection conn, int startPos, int endPos, String localFile, CyclicBarrier barrier){ + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.localFile = localFile; + this.barrier = barrier; + } + public void run(){ + + + try { + System.out.println("Begin to read [" + startPos +"-"+endPos+"]"); + //调用read + byte[] data = conn.read(startPos, endPos); + + RandomAccessFile file = new RandomAccessFile(localFile,"rw"); + //类似指针指到开始处 + file.seek(startPos); + //把数据写入 + file.write(data); + + file.close(); + + conn.close(); + + barrier.await(); //等待别的线程完成 + + } catch (Exception e) { + e.printStackTrace(); + + } + } +} diff --git a/group27/1016908591/week03/src/com/coderising/download/FileDownloader.java b/group27/1016908591/week03/src/com/coderising/download/FileDownloader.java new file mode 100644 index 0000000000..632cf676fb --- /dev/null +++ b/group27/1016908591/week03/src/com/coderising/download/FileDownloader.java @@ -0,0 +1,142 @@ +package com.coderising.download; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.api.DownloadListener; + + +public class FileDownloader { + + String url; + private String localFile; + + DownloadListener listener; + + ConnectionManager cm; + private String loaclFile; + + + private static final int DOWNLOAD_TRHEAD_NUM = 3; + + public FileDownloader(String _url, String localFile) { + this.url = _url; + this.localFile = localFile; + + } + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (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方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + CyclicBarrier barrier = new CyclicBarrier(DOWNLOAD_TRHEAD_NUM , new Runnable(){ + public void run(){ + listener.notifyFinished(); + } + }); + Connection conn = null; + + try { + conn = cm.open(this.url); + int length = conn.getContentLength(); + + createPlaceHolderFile(this.loaclFile,length); + int[][] ranges = allocateDownloadRange(DOWNLOAD_TRHEAD_NUM, length); +for(int i=0; i< DOWNLOAD_TRHEAD_NUM; i++){ + + + DownloadThread thread = new DownloadThread( + cm.open(url), + ranges[i][0], + ranges[i][1], + localFile, + barrier); + + thread.start(); + } + + } catch (Exception e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + + + + + } + + + + + + + + + + private int[][] allocateDownloadRange(int threadNum, int contentLen) { + int[][] ranges = new int[threadNum][2]; + //文件长度除去线程个数 + int eachThreadSize = contentLen / threadNum;// 每个线程需要下载的文件大小 + //记录余数 + int left = contentLen % threadNum;// 剩下的归最后一个线程来处理 + //对线程数目做一个循环 + for(int i=0;i totalLen){ + byte[] data = baos.toByteArray(); + return Arrays.copyOf(data, totalLen); + } + } + + return baos.toByteArray(); + + } + + @Override + public int getContentLength() { + + URLConnection con; + try { + con = url.openConnection(); + + return con.getContentLength(); + + } catch (IOException e) { + e.printStackTrace(); + } + + return -1; + } + + @Override + public void close() { + + + } + +} diff --git a/group27/1016908591/week03/src/com/coderising/download/impl/ConnectionManagerImpl.java b/group27/1016908591/week03/src/com/coderising/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..8b7e9cc665 --- /dev/null +++ b/group27/1016908591/week03/src/com/coderising/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,14 @@ +package com.coderising.download.impl; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + + return new ConnectionImpl(url); + } + +} diff --git a/group27/1016908591/week03/src/com/coderising/download/test/ConnectionTest.java b/group27/1016908591/week03/src/com/coderising/download/test/ConnectionTest.java new file mode 100644 index 0000000000..6c127cb054 --- /dev/null +++ b/group27/1016908591/week03/src/com/coderising/download/test/ConnectionTest.java @@ -0,0 +1,57 @@ +package com.coderising.download.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.impl.ConnectionManagerImpl; + +public class ConnectionTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + //测试连接url的功能 + public void testContentLength() throws Exception{ + //new一个接口,然后实现这个接口 + ConnectionManager connMan = new ConnectionManagerImpl(); + Connection conn = connMan.open("http://www.hinews.cn/pic/0/13/91/26/13912621_821796.jpg"); + Assert.assertEquals(35470, conn.getContentLength()); + } + + @Test + //测试读入,确保设计的接口ok + public void testRead() throws Exception{ + + ConnectionManager connMan = new ConnectionManagerImpl(); + Connection conn = connMan.open("http://www.hinews.cn/pic/0/13/91/26/13912621_821796.jpg"); + + byte[] data = conn.read(0, 35469); + + Assert.assertEquals(35470, data.length); + + data = conn.read(0, 1023); + + Assert.assertEquals(1024, data.length); + + data = conn.read(1024, 2023); + + Assert.assertEquals(1000, data.length); + + + // 测试不充分,没有断言内容是否正确 + } + + + + +} diff --git a/group27/1016908591/week03/src/com/coderising/download/test/FileDownloaderTest.java b/group27/1016908591/week03/src/com/coderising/download/test/FileDownloaderTest.java new file mode 100644 index 0000000000..40f01fd9ac --- /dev/null +++ b/group27/1016908591/week03/src/com/coderising/download/test/FileDownloaderTest.java @@ -0,0 +1,66 @@ +package com.coderising.download.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.download.FileDownloader; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.api.DownloadListener; +import com.coderising.download.impl.ConnectionManagerImpl; + +public class FileDownloaderTest { + boolean downloadFinished = false; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + /*题 一般的时候是网络连接的问题。还有你可以设置一下 服务器的超时时间。有的可能是三十秒。你试试更长点的。 + * 还有一种可能性是。你程序里创建了很多connection 但是没有关闭调。现在数据库处于半死状态,然后连接超时。 + * 你ping的是服务器的ip吗? 你可以用plsql检验一下你的网络是否通。还有配置服务器数据源的时候 如果能配置成功, + * 那网络也没问题。 + */ + //String url = "http://www.hinews.cn/pic/0/13/91/26/13912621_821796.jpg"; + + String url = "http://images2015.cnblogs.com/blog/610238/201604/610238-20160421154632101-286208268.png"; + + FileDownloader downloader = new FileDownloader(url,"e:\\项目练手\\test.jpg"); + + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + + }); + + + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + + + + } + +} diff --git a/group27/1016908591/week03/src/com/coding/basic/LinkedList.java b/group27/1016908591/week03/src/com/coding/basic/LinkedList.java new file mode 100644 index 0000000000..8efd566a00 --- /dev/null +++ b/group27/1016908591/week03/src/com/coding/basic/LinkedList.java @@ -0,0 +1,283 @@ +package com.coding.basic; +import javax.xml.crypto.Data; + + + +public class LinkedList implements List { + + private Node head; + private int length; + //构造函数 + public LinkedList(){ + clear(); + } + public final void clear(){ + head = null; + length = 0; + } + + public void add(Object o){ + Node newNode = new Node(o); + if(length == 0) + { + head = newNode; + } + else{ + Node lastNode = getNodeAt(length); + lastNode.next = newNode; + + } + length++; + + + } + public void add(int index , Object o){ + Node newNode = new Node(o); + Node nodeBefor = getNodeAt(index-1); + Node nodeAfter = nodeBefor.next; + newNode.next = nodeAfter; + nodeBefor.next = newNode; + length++; + + + } + public Object get(int index){ + if((1<=index)&&(index<=length)) + { + Node currentNode = head; + for(int i= 0;i7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + + Node lastNode = getNodeAt(length); + head = lastNode; + while(length>0){ + Node currentNode = getNodeAt(--length); + add(currentNode); + + } + + + + + + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + int num = length/2; + while(num>0){ + remove(num); + num--; + } + + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + while (length>0){ + remove(i+length); + length--; + } + + } + /** + * 假定当前链表和list均包含已升序排列的整数 + * 从当前链表中取出那些list所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + int[] arr = new int[list.size()]; + + for(int i =0;idata) + remove(i); + } + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + if(list==null){ + return null; + } + int i1 = 0; + int i2 = 0; + LinkedList result = new LinkedList(); + Node currentListNode = list.head; + Node currentThisNode = this.head; + for(i1 =0;i1