用java做抓取的时候免不了要用到多线程的了,因为要同时抓取多个网站或一条线程抓取一个网站的话实在太慢,而且有时一条线程抓取同一个网站的话也比较浪费CPU资源。要用到多线程的等方面,也就免不了对线程的控制或用到线程池。   我在做我们现在的那一个抓取框架的时候,就曾经用过java.util.concurrent.ExecutorService作为线程池,关于ExecutorService的使用代码大概如下:
java.util.concurrent.Executors类的API提供大量创建连接池的静态方法:1.固定大小的线程池:

package BackStage;

 import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService; public class JavaThreadPool {
public static void main(String[] args) {
// 创建一个可重用固定线程数的线程池
ExecutorService pool = Executors.newFixedThreadPool(2);
// 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
// 将线程放入池中进行执行
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
// 关闭线程池
pool.shutdown();
}
} class MyThread extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执行。。。");
}
}

后来发现ExecutorService的功能没有想像中的那么好,而且最多只是提供一个线程的容器而然,所以后来我用改用了java.lang.ThreadGroup,ThreadGroup有很多优势,最重要的一点就是它可以对线程进行遍历,知道那些线程已经运行完毕,还有那些线程在运行。关于ThreadGroup的使用代码如下:

class MyThread extends Thread {
boolean stopped; MyThread(ThreadGroup tg, String name) {
super(tg, name);
stopped = false;
} public void run() {
System.out.println(Thread.currentThread().getName() + " starting.");
try {
for (int i = 1; i < 1000; i++) {
System.out.print(".");
Thread.sleep(250);
synchronized (this) {
if (stopped)
break;
}
}
} catch (Exception exc) {
System.out.println(Thread.currentThread().getName() + " interrupted.");
}
System.out.println(Thread.currentThread().getName() + " exiting.");
} synchronized void myStop() {
stopped = true;
}
} public class Main {
public static void main(String args[]) throws Exception {
ThreadGroup tg = new ThreadGroup("My Group"); MyThread thrd = new MyThread(tg, "MyThread #1");
MyThread thrd2 = new MyThread(tg, "MyThread #2");
MyThread thrd3 = new MyThread(tg, "MyThread #3"); thrd.start();
thrd2.start();
thrd3.start(); Thread.sleep(1000); System.out.println(tg.activeCount() + " threads in thread group."); Thread thrds[] = new Thread[tg.activeCount()];
tg.enumerate(thrds);
for (Thread t : thrds)
System.out.println(t.getName()); thrd.myStop(); Thread.sleep(1000); System.out.println(tg.activeCount() + " threads in tg.");
tg.interrupt();
}
}

由以上的代码可以看出:ThreadGroup比ExecutorService多以下几个优势

1.ThreadGroup可以遍历线程,知道那些线程已经运行完毕,那些还在运行

2.可以通过ThreadGroup.activeCount知道有多少线程从而可以控制插入的线程数

ThreadGroup其实比ExecutorService更好的更多相关文章

  1. Netty5序章之BIO NIO AIO演变

    Netty5序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使 ...

  2. Netty序章之BIO NIO AIO演变

    Netty序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用 ...

  3. JDK的BIO, NIO, AIO

    背景知识点我 1. BIO JDK5之前, JDK的IO模式只有BIO(同步阻塞)问题: 因为阻塞的存在, 需对每个请求开启一个线程. 过多的线程切换影响操作系统性能解决: 使用线程池, 处理不过来的 ...

  4. Java IO------------------BIO(同步阻塞)、NIO1.0(多路复用)、NIO2.0(AIO,非阻塞)

    1. BIO JDK5之前, JDK的IO模式只有BIO(同步阻塞)问题: 因为阻塞的存在, 需对每个请求开启一个线程. 过多的线程切换影响操作系统性能解决: 使用线程池, 处理不过来的放入队列, 再 ...

  5. Java 网络IO编程(BIO、NIO、AIO)

    本概念 BIO编程 传统的BIO编程 代码示例: public class Server { final static int PROT = 8765; public static void main ...

  6. java IO(BIO)、NIO、AIO

    IO 服务端ServerSocket 客户端Socket 缺点每次客户端建立连接都会另外启一个线程处理.读取和发送数据都是阻塞式的. 如果1000个客户端建立连接将会产生1000个线程 Server端 ...

  7. BIO/NIO/AIO的区分(十四)

    BIO:同步阻塞IO(平常说的IO指的是BIO)NIO:同步非阻塞IOAIO:异步非阻塞IO io操作分为两部分,发起io请求,和io数据读写. 阻塞.非阻塞主要是针对线程发起io请求后,是否立即返回 ...

  8. 1.IO的演进

      1.Java IO 演进之路 本文围绕着一下几个问题 1.Java 中 BIO.NIO.AIO 之间的区别及应用场景. 2.阻塞(Block)与非阻塞(Non-Block)区别. 3.同步(Syn ...

  9. Java中的IO、NIO、File、BIO、AIO详解

    java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?         Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包 ...

随机推荐

  1. JS 数组位置方法 indexOf()和lastIndexOf()的理解

    var numbers = [1,3,5,7,9,4,3,2,1]; console.log(numbers.indexOf(5)); //从数组的0位开始查找 5 位于数组里面的位置 输出2 首先 ...

  2. Linux 操作系统主机名变成bogon怎么解决?

    主机名变成bogon怎么解决? by:授客 QQ:1033553122   一:使用hostname命令 [laiyu@localhost ~]$ hostname localhost.localdo ...

  3. Android Studio列表用法之一:ListView图文列表显示(实例)

    前言: ListView这个列表控件在Android中是最常用的控件之一,几乎在所有的应用程序中都会使用到它. 目前正在做的一个记账本APP中就用到了它,主要是用它来呈现收支明细,是一个图文列表的呈现 ...

  4. (后端)SQL Server日期时间函数

    转自博客园: 1.获取当前日期GetDate getdate()函数以datetime数据类型的格式返回当前SQLServer服务器所在计算机的日期和时间.其语法格式为getdate().返回值舍入到 ...

  5. [20171121]rman backup as copy 2.txt

    [20171121]rman backup as copy 2.txt --//昨天测试backup as copy ,备份时备份文件的文件头什么时候更新.是最后完成后还是顺序写入备份文件.--//我 ...

  6. python第六十八天--第十二周作业

    主题: 需求: 用户角色,讲师\学员, 用户登陆后根据角色不同,能做的事情不同,分别如下讲师视图 管理班级,可创建班级,根据学员qq号把学员加入班级 可创建指定班级的上课纪录,注意一节上课纪录对应多条 ...

  7. woff字体MIME类型配置

    <system.webServer> <staticContent> <remove fileExtension=".woff" /> < ...

  8. win7系统开机后电脑桌面背景变黑的解决方法

    自从微软放弃了对win7系统的维护更新,一些BUG也就慢慢出现了,最近用户反映,开机后电脑桌面背景变黑,即使重新换了桌面背景,还是会出现这种情况.下面小编就来告诉大家怎样解决这一问题. 1.点击开始菜 ...

  9. LNMP环境搭建详细教程

    之前有一篇博客写的是LAMP的环境搭建,今天来详细介绍一下另外一个模式——LNMP=Linux+Nginx+MySQL+PHP. 一.在Linux系统下nginx的安装过程,先到http://ngin ...

  10. 截取字符串substr和subString的却别

    substr 方法 返回一个从指定位置开始的指定长度的子字符串. stringvar.substr(start [, length ]) 参数 stringvar 必选项.要提取子字符串的字符串文字或 ...