多线程网络爬虫

线程-生产者消费者

emmm…今天下午开始要利用java做一个爬虫为课设的数据库数据做准备,以前的爬虫设计用的是连接池爬虫池,但是效率不怎么样,所以补充线程上的一些知识,

先看这张图

在这里插入图片描述
大家都知道网络请求是一个非常耗时的一个问题,因为影响这个的因素很多,一个请求发送你可能要等好久才内得到io返回的数据,所以我们把程序设计成线程碎片化处理,分为3个部分,1就是网络请求部分,2数据解析部分,3数据持久化部分,1-2和2-3中我们用产品池差不多的概念作为连接,网络请求部分我们就可以多放几个线程去爬虫,2,3部分相比之下比第一部分耗时低的不是一个等级,这些也是我自己在学到Linux线程的时候收到的启发,并发的去处理问题,这样的效率会比串行的解决问题更高,
具体某个部分开几个线程和池子给多大,这个取决于最主要1、网速,2、运行内存,3、CPU等数据库原因,这个我也不好评估,各位有什么好建议可以评论区里面写,
下面我们来看线程中的生产者和消费者吧

1、我们先定义一个资源

/**
 * 商品
 */
public class Product {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Product(String name){
        this.name = name;
    }

}

2、定义一个资源池

/**
 * 商品池
 */
public class ProductPool {
    /*
    * 存储产品的集和
    * 生产者生产
    * 消费者消费产品
    * */
    private List<Product> products;

    private int maxSize = 0;

    public ProductPool(int maxSize) {
        this.products = new LinkedList<>();
        this.maxSize = maxSize;
    }

    /**
     * 生产者讲商品存放到商品池
     * @param product
     */
    public synchronized void pust(Product product){
        //判断商品池里面的商品是不是已经满了
        if (products.size()==maxSize-1){
            try {
                //线程进入等待池里面
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }else {
            products.add(product);
            //通知其他人可以消费了
            this.notifyAll();
        }
    }

    public synchronized Product pop(){
        if (products.size() == 0){
            try {
                //进入等待队列中
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        Product product = this.products.remove(0);
        this.notifyAll();
        return product;

    }

    public synchronized int size(){
        return this.products.size();
    }
}

3、生产者

/**
 * 生产者
 */
public class Productor implements Runnable {

    private ProductPool pool;

    public Productor(ProductPool productPool){
        this.pool = productPool;
    }

    @Override
    public void run() {
        while (true){
            String productName = (int)(Math.random()*100)+":号产品";
            pool.pust(new Product(productName));
            System.out.println(Thread.currentThread().getName()+"线程生产了:"+productName+",剩余"+pool.size());
            try {
                //模拟生产者生产休眠
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

4、消费者

/**
 * 生产者
 */
public class Consumer implements Runnable {

    private ProductPool pool;

    public Consumer(ProductPool productPool){
        this.pool = productPool;
    }

    @Override
    public void run() {
        while (true){
            Product product = pool.pop();
            String productName = product.getName();
            System.out.println(Thread.currentThread().getName()+"线程消费了:"+productName);
            try {
                //模拟消费者休眠
                Thread.sleep(70);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

5、运行

public class Program {

    public static void main(String[] args) {
        //实例化一个产品池对象
        ProductPool productPool = new ProductPool(100);

        Thread productor = new Thread(new Productor(productPool),"1号");
        Thread productor3 = new Thread(new Productor(productPool),"3号");
        productor.start();
        productor3.start();
        Thread consumer = new Thread(new Consumer(productPool),"2号");
        consumer.start();

    }

}

6、运行结果

3号线程生产了:98:号产品,剩余1
1号线程生产了:45:号产品,剩余1
2号线程消费了:45:号产品
2号线程消费了:98:号产品
1号线程生产了:84:号产品,剩余1
3号线程生产了:47:号产品,剩余2
2号线程消费了:84:号产品
3号线程生产了:47:号产品,剩余3
1号线程生产了:24:号产品,剩余3
2号线程消费了:47:号产品
2号线程消费了:47:号产品
3号线程生产了:97:号产品,剩余2
1号线程生产了:30:号产品,剩余3
2号线程消费了:24:号产品
3号线程生产了:89:号产品,剩余4
1号线程生产了:66:号产品,剩余4
2号线程消费了:97:号产品
2号线程消费了:30:号产品
3号线程生产了:96:号产品,剩余4
1号线程生产了:24:号产品,剩余4

ok再见

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值