线程池简单例子

来源:互联网 发布:怎么在淘宝上发布宝贝 编辑:程序博客网 时间:2024/05/22 05:33

文案摘自:《Java 编程思想》
FixedThreadPool
使用了有限的线程集来执行所提交的任务。还提供了一种重要的并发保证,其他线程不会(即没有两个线程会)被并发调用。这会改变任务的加锁需求。(超过限定的线程会排队等待,在已运行的线程结束后,开始执行)

CachedThreadPool
在程序执行过程中通常会创建与所需数量相同的线程,然后在它回收旧线程时停止创建新线程

SingleThreadExecutor
就像是线程数量为1的FixedThreadPool。这对于你希望再另一个线程中连续运行的任何事物(长期存活的任务)来说,都是很有用的,例如监听进入的套接字连接的任务。它对于希望在线程中运行的短任务也同样很方便,例如,更新本地或远程日志的小任务,或者是事件分发线程。
如果向SingleThreadEcecutor提交了多个任务,那么这些任务将排队,每个任务都会在下一个任务开始之前运行结束,所有的任务将使用相同的线程。因此,SingleThreadExecutor会序列化所有提交给它的任务,并会维护它自己(隐藏)的悬挂任务队列。

下面是自己写的对应的简单例子
好,下面开始贴代码,然后大概说两句

IntelliJ IDEA 新建工程:ExecutorDemo

新建类:ExecutorFactory,代码如下

public class ExecutorFactory {    public static ExecutorService create(String type) {        ExecutorService service = null;        switch (type) {            case "cache":                service = Executors.newCachedThreadPool();                break;            case "fixed"://注意:这里创建的线程池限定最大是2                service = Executors.newFixedThreadPool(2);                break;            case "single":                service = Executors.newSingleThreadExecutor();                break;        }        return service;    }}

新建类:ExecutorDemo,代码如下

public class ExecutorDemo {    private ExecutorService service;    public ExecutorDemo(String type) {        service = ExecutorFactory.create(type);    }    public Future<?> submit(RunnableClass runnable) {        return service.submit(runnable);    }    public void execute(RunnableClass runnable) {        service.execute(runnable);    }    public void release() {        service.shutdown();    }}

新建类:RunnableClass,代码如下

public class RunnableClass implements Runnable {    private static int taskCount = 0;    private final int id = taskCount++;    @Override    public void run() {        System.out.println("id:" + id + "开始");        try {            TimeUnit.MILLISECONDS.sleep(100);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("id:" + id + ",完成");    }}

新建类:ExecutorMainTest,代码如下

public class ExecutorMainTest{    public static void main(String[] args) {        DemoTest test = new DemoTest();//        test.test("cache");//        test.test("fixed");//        test.test("single");    }    public void test(String type) {        ExecutorDemo demo = new ExecutorDemo(type);        for (int i = 0; i < 5; i++) {            demo.execute(new RunnableClass());        }        demo.release();    }}

下面为ExecutorMainTest中,不同的testType的测试结果:

test.test(“cache”)的结果是

id:1开始id:0开始id:2开始id:3开始id:4开始id:0,完成id:1,完成id:2,完成id:4,完成id:3,完成

因为CachedThreadPool会创建与所需数量相同的线程,所以看到的结果是,连续创建了足够的线程后,然后输出结果

下面是test.test(“fixed”)的输出结果

id:0开始id:1开始id:0,完成id:1,完成id:2开始id:3开始id:3,完成id:2,完成id:4开始id:4,完成

因为在ExecutorFactory中创建FixedThreadPool时,限定了最大的线程数是2,所以看到的结果是:先创建两个线程,然后等这两个线程执行完成后,在复用这两个线程执行新的任务,等执行完毕后再复用,直到任务结束。

下面是test.test(“single”)的执行输出结果

id:0开始id:0,完成id:1开始id:1,完成id:2开始id:2,完成id:3开始id:3,完成id:4开始id:4,完成

因为SingleThreadExecutor中只有一个线程在运行,所以看到的结果是,创建一个线程执行完成,再复用,进行下一个任务,直到结束。

execute和submit方法的区别是:
1、接收的参数不一样
2、submit有返回值,而execute没有
3、submit方便Exception处理
具体可参考:ExecutorService的execute和submit方法

好了,大概先说这么多
代码地址:
https://github.com/b1234569856/JavaDemo