文案摘自:《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