这篇文章主要为大家详细介绍了 java ExecutorService 使用方法, 具有一定的参考价值, 感兴趣的小伙伴们可以参考一下
下面的例子主要讨论两个问题:
问题 1. 线程池固定大小, 假设为 5. 那么向线程池放入 10 个线程, 运行效果如何? 其他线程的状态?
问题 2. 那么如何从线程池中移除某一个线程, 确切说是使某一个线程成为空闲线程?
例子:
- package com.dada.executorService;
- import java.util.concurrent.TimeUnit;
- public class JobThread extends Thread {
- // 为线程命名
- public JobThread(String name,long threadId) {
- super(name);
- }
- @Override
- public void run() {
- // 如果主线程包含这个线程就一直运行
- while (MainThread.threadNameMap.containsKey(this.getName())) {
- try {
- System.out.println("线程名称:-----" + this.getName());
- TimeUnit.SECONDS.sleep(4);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- System.out.println("*************** 线程结束, 线程名称:*********" + this.getName());
- }
- }
- package com.dada.executorService;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.TimeUnit;
- public class MainThread {
- public static final int THREADPOOL_SIZE = 5;
- // 生成固定大小的线程池
- public static ExecutorService exec = Executors.newFixedThreadPool(THREADPOOL_SIZE);
- // 用来存储线程名称的 map
- public static Map < String,
- String > threadNameMap = new HashMap < String,
- String > ();
- public static void main(String[] args) {
- // 向线程池中插入 10 个线程, 但是线程池只允许最大 5 个线程, 所以其他 5 个线程等待中
- for (int i = 0; i < THREADPOOL_SIZE + 5; i++) {
- String threadName = getThreadName(i);
- threadNameMap.put(threadName, threadName);
- exec.execute(new JobThread(threadName, i));
- }
- System.out.println("Hash 表的 Size:" + threadNameMap.size());
- try {
- System.out.println("主线程睡一会!");
- TimeUnit.SECONDS.sleep(3);
- } catch(Exception e) {
- e.printStackTrace();
- System.out.println("醒了!");
- }
- // 下面的这几个用来删除线程池里面的线程
- //removeThread(0);
- //removeThread(1);
- //removeThread(2);
- }
- public static void removeThread(int i) {
- threadNameMap.remove(getThreadName(i));
- System.out.println("删除线程 Thread" + i + ", Hash 表的 Size:" + threadNameMap.size());
- }
- public static String getThreadName(int i) {
- return "threadname" + i;
- }
- }
直接运行代码结果:
线程名称:-----threadname0
Hash 表的 Size:10
主线程睡一会!
线程名称:-----threadname2
线程名称:-----threadname4
线程名称:-----threadname1
线程名称:-----threadname3
线程名称:-----threadname4
线程名称:-----threadname2
线程名称:-----threadname3
线程名称:-----threadname1
线程名称:-----threadname0
线程名称:-----threadname1
线程名称:-----threadname3
线程名称:-----threadname0
线程名称:-----threadname4
线程名称:-----threadname2
线程名称:-----threadname1
线程名称:-----threadname3
线程名称:-----threadname4
结论:
发现打印的: 线程名称一直从 threadname0 到 threadname4, 没有其他的名称
由此证明: 向线程池中放入 10 个线程, 但是线程池的大小为 5, 只能给 5 个线程分配 CPU, 运行的就是最先放入线程池中的 5 个线程, 其他线程都处于就绪状态(阻塞状态)
去掉注释之后代码运行结果:
线程名称:-----threadname0
线程名称:-----threadname2
线程名称:-----threadname4
Hash 表的 Size:10
主线程睡一会!
线程名称:-----threadname1
线程名称:-----threadname3
删除线程 Thread0, Hash 表的 Size:9
删除线程 Thread1, Hash 表的 Size:8
删除线程 Thread2, Hash 表的 Size:7
*************** 线程结束, 线程名称:*********threadname2
*************** 线程结束, 线程名称:*********threadname0
线程名称:-----threadname5
线程名称:-----threadname6
*************** 线程结束, 线程名称:*********threadname1
线程名称:-----threadname4
线程名称:-----threadname7
线程名称:-----threadname3
线程名称:-----threadname6
线程名称:-----threadname5
线程名称:-----threadname7
线程名称:-----threadname4
线程名称:-----threadname3
线程名称:-----threadname5
线程名称:-----threadname6
线程名称:-----threadname7
线程名称:-----threadname4
线程名称:-----threadname3
结论:
从结果中可以看出, 在移除线程之前, 运行的线程还是从 thread0 到 thread4 当移除线程 thread0 后, 新的线程 thread3 开始运行, 而且是按照顺序到 threadname7
总结如下:
1. 线程池固定大小, 假设为 5. 那么向线程池放入 10 个线程, 运行效果如何? 其他线程的状态?
a. 线程池的概念就是你不断的向其中 push 请求, 但是它只能处理规定额度的线程, 多余的线程都会在其中等待
b. 当其中一个线程处理完毕(业务执行完毕或退出 while 循环), 线程池就会自动从等待的队列中取出一个作业, 使用空闲的线程来运行这个作业运行线程池中的哪个, 从例子上来看应该是按照被放入的先后顺序来的
2. 那么如何从线程池中移除某一个线程, 确切说是使某一个线程成为空闲线程?
线程池无法获取其中某一个线程并杀掉他, 因为使用线程池的主线程和主线程开启的线程是平级的, 谁都无权主宰另一方的存亡但是可以换一个方式, 委婉的达到目的
a. 主线程维护一个 Hash 表可以是一个 HashMapkey 值任意, 但是要唯一, 可以唯一标示一个线程
b. 所有放入线程池的线程, 都要生成一个 key 值, 然后存入这个 HashMap 中
c. 对于循环类的线程, 如 while(true)的线程需要增加一个条件, 每一轮循环校验这个线程的 key 是否存在于上面 HashMap 中如果不存在则退出 while 循环
d. 虽然主线程不可以主宰其他线程的存亡, 但是可以对自己的 HashMap 进行 put 或是 remove 操作到此, 只要从 HashMap 中移除线程对应的 Key 值, 这个线程在下次循环的时候就会自动退出了
来源: http://www.phperz.com/article/18/0226/359280.html