java在2007年的时候编写过多线程爬虫,当时对多线程的理解仅仅限于可以同时并发任务,对于多线程之间的调度,完全没有理解。所以后来这的多线程的应用仅仅限于只能多线程并发任务。其实一切在线程中都可以被监控。
看下面的列子,我们来理解多线程之间如何进行控制的。
代码如下 | 复制代码 |
package com.javaer.thread; public class PrintABC { public static Boolean isThreadA = true; public static Boolean isThreadB = false; public static Boolean isThreadC = false; public static void main(String[] args) { final PrintABC abc = new PrintABC(); new Thread(new Runnable() { public void run() { for (int i = 0; i < 10; i++) { synchronized (abc) { while (!isThreadA) { try { abc.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.print("A"); isThreadA = false; isThreadB = true; isThreadC = false; abc.notifyAll(); } } } }).start(); new Thread(new Runnable() { public void run() { for (int i = 0; i < 10; i++) { synchronized (abc) { while (!isThreadB) { try { abc.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.print("B"); isThreadA = false; isThreadB = false; isThreadC = true; abc.notifyAll(); } } } }).start(); new Thread(new Runnable() { public void run() { for (int i = 0; i < 10; i++) { synchronized (abc) { while (!isThreadC) { try { abc.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.print("C"); isThreadA = true; isThreadB = false; isThreadC = false; abc.notifyAll(); } } } }).start(); } } |
输出结果如下 :ABCABCABCABCABC
思路:解题思路大概是这样的,开启三个线程,每个线程一次打印一个字母,并且按照一定的顺序打印,当打印A的时候,其他线程处于阻塞状态,打印完A以后,将线程解锁,让打印B的那个线程开启,其他线程处于阻塞状态,同理打印C的时候,阻塞其他线程,这三个线程顺序循环,就达到顺序多次打印ABC的目的了。
这道题看似思路简单,其实主要需要用到wait()方法和notify()方法,还有关键字synchronized,只有充分理解了这些,才能解出这道题。下面我有必要讲解一下这两个方法,还有关键字synchronized。
多线程并行下载的核心特点就是分段,并行下载。
比如一个文件200M,分5个线程,那么就给砍成5份,分别同时下就好了。速度当然比一点点下载来的要快的多。
代码如下 | 复制代码 |
package com.javaer.examples.file; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; public class MyMutilDown { /** * 单线程的远程下载 */ public void SingleDown(String filePath, String url) { try { // 要写入的文件 File file = new File(filePath + getFileExtName(url)); FileWriter fWriter = new FileWriter(file); URL ul = new URL(url); URLConnection conn = ul.openConnection(); conn.setConnectTimeout(2000);// 请求超时时间 // int len = conn.getContentLength(); InputStream in = conn.getInputStream(); // byte[] by = new byte[1024]; int temp = 0; while ((temp = in.read()) != -1) { System.out.println(temp); fWriter.write(temp); } fWriter.close(); in.close(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 文件后缀名 * * @param path * @return */ public String getFileExtName(String path) { return path.substring(path.lastIndexOf(".")); } /** * 测试多线程 * * @param filePath * 文件保存路径 * @param url * url * @param tnum * 线程数量 */ public void MutiDown(String filePath, String url, int tnum) { try { // 要写入的文件 final File file = new File(filePath + getFileExtName(url)); System.out.println(file.getAbsolutePath()); RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");// 建立随机访问 final URL ul = new URL(url); HttpURLConnection conn = (HttpURLConnection) ul.openConnection(); conn.setConnectTimeout(2000);// 请求超时时间 conn.setRequestMethod("GET"); int len = conn.getContentLength();// 文件长度 accessFile.setLength(len); accessFile.close(); final int block = (len + tnum - 1) / tnum;// 每个线程下载的快大小 for (int i = 0; i < tnum; i++) { final int a = i; new Thread(new Runnable() { int start = block * a;// 开始位置 int end = block * (a + 1) - 1;// 结束位置 @Override public void run() { HttpURLConnection conn2 = null; RandomAccessFile accessFile2 = null; InputStream in = null; try { conn2 = (HttpURLConnection) ul.openConnection(); conn2.setConnectTimeout(2000);// 请求超时时间 conn2.setRequestMethod("GET"); // TODO Auto-generated method stub conn2.setRequestProperty("Range", "bytes=" + start + "-" + end + "");// 设置一般请求属性 范围 in = conn2.getInputStream(); byte[] data = new byte[1024]; int len = 0; accessFile2 = new RandomAccessFile(file, "rwd"); accessFile2.seek(start); while ((len = in.read(data)) != -1) { System.out.println(a + "/" + len); accessFile2.write(data, 0, len);//并发写入 } System.out.println("线程:" + a + "下载完成!"); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } finally { try { accessFile2.close(); in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }).start(); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { MyMutilDown mydown = new MyMutilDown(); String path = "http://www.111cn.net/ openx-220080603.rar"; // mydown.SingleDown("/", path); mydown.MutiDown("/bbc", path, 3); } } |
注明:本文版权属于ITeye会员 lohasle
时间: 2024-09-26 03:44:02