Java并发抓取网络图片

通过使用CyclicBarrier类来实现并发抓取网络图片:

CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为 循环 的 barrier。
CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此 屏障操作 很有用。

实现的下载器代码如下:

package com.kkoolerter;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * 多线程网络图片下载器
 *
 * @author Jenson
 *
 */
public class Downloader extends Thread {

    private CyclicBarrier cb;
    private String urlStr;
    private String saveFileName;

    public Downloader(String name, String url, String saveFileName,
            CyclicBarrier cb) {
        this.setName(name);
        this.cb = cb;
        this.urlStr = url;
        this.saveFileName = saveFileName;
    }

    @Override
    public void run() {
        try {
            System.out.println("开始下载"+this.saveFileName+"...");
            URL url = new URL(this.urlStr);
            DataInputStream dis = new DataInputStream(url.openStream());
            OutputStream fos = new FileOutputStream(new File(this.saveFileName));
            byte[] buff = new byte[1024];
            int len = -1;
            while((len = dis.read(buff))!=-1){
                fos.write(buff, 0, len);
            }
            buff = null;
            fos.close();
            dis.close();
            System.out.println("下载文件"+this.saveFileName+"完成");
            this.cb.await();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

测试代码:

package com.kkoolerter;

import java.util.concurrent.CyclicBarrier;

public class CycleBarrierDemo {

   
    public static void main(String[] args) {
         CyclicBarrier cb = new CyclicBarrier(10);
         new Downloader("d1", "http://img2.3lian.com/img2007/17/08/001.jpg", "001.jpg", cb).start();
         new Downloader("d2", "http://img2.3lian.com/img2007/17/08/002.jpg", "002.jpg", cb).start();
         new Downloader("d3", "http://img2.3lian.com/img2007/17/08/003.jpg", "003.jpg", cb).start();
         new Downloader("d4", "http://img2.3lian.com/img2007/17/08/004.jpg", "004.jpg", cb).start();
         new Downloader("d5", "http://img2.3lian.com/img2007/17/08/005.jpg", "005.jpg", cb).start();
         new Downloader("d6", "http://img2.3lian.com/img2007/17/08/006.jpg", "006.jpg", cb).start();
         new Downloader("d7", "http://img2.3lian.com/img2007/17/08/007.jpg", "007.jpg", cb).start();
         new Downloader("d8", "http://img2.3lian.com/img2007/17/08/008.jpg", "008.jpg", cb).start();
         new Downloader("d9", "http://img2.3lian.com/img2007/17/05/0849m.jpg", "0849m.jpg", cb).start();
         new Downloader("d10", "http://img2.3lian.com/img2007/17/05/08943m.jpg", "0849m.jpg", cb).start();
    }

}

上述示例在我的电脑运行的结果如下:

开始下载001.jpg...
开始下载002.jpg...
开始下载004.jpg...
开始下载006.jpg...
开始下载008.jpg...
开始下载0849m.jpg...
开始下载003.jpg...
开始下载005.jpg...
开始下载0849m.jpg...
开始下载007.jpg...
下载文件002.jpg完成
下载文件007.jpg完成
下载文件001.jpg完成
下载文件003.jpg完成
下载文件006.jpg完成
下载文件0849m.jpg完成
下载文件004.jpg完成
下载文件0849m.jpg完成
下载文件008.jpg完成
下载文件005.jpg完成


参考文献:JDK文档

你可能感兴趣的:(java,多线程,并发,职场,休闲)