线程池的创建
【摘要】 什么是线程池以及创建线程池的方法
一、线程池
首先概括一下线程池的概念,线程池相当于一个包装袋,袋子里有多个线程,在没有任务时,这些线程都是睡眠的,当有任务需要执行某个程序时,会调用相应的线程,被调用的线程会醒,执行过后继续睡眠。系统可以同时调用多个线程。
通过线程池可以启动多线程,Executors的工具类可以创建线程。线程池的有以下几个有点:
- 提高系统响应速度,当有任务时,复用已存在的线程,无需等待新的线程创建就可以立即执行任务
- 降低系统资源消耗,复用已存在的线程,降低了新建和销毁线程的损耗
- 方便线程管控,因为线程如果无限制创建,会占用过多的内存,并且造成cpu切换过渡
二、创建线程池
1.FixThreadPool(int n)固定大小的线程池
public class FixThreadPoolTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建固定大小线程的线程池
ExecutorService ex = Executors.newFixedThreadPool(3);
//用线程池执行任务
for(int i = 0;i<3;i++) {
ex.submit(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int j = 0;j<10;j++) {
System.out.println(Thread.currentThread().getName()+" "+j);
}
}
});
}
// ex.submit(new Runnable() {
//
// @Override
// public void run() {
// // TODO Auto-generated method stub
// for(int j = 0;j<10;j++) {
// System.out.println(Thread.currentThread().getName()+" "+j);
// }
// }
//
// });只创建一个线程
//关闭线程池,会把原先的任务执行完,但不会再执行新的任务
ex.shutdown();
//通过结果表明,三个线程一共要执行5次,每个线程执行次数是随机的
2.SingleThreadPoolExcutor单线程池
单线程池只能创建一个线程,优点是能够串行执行任务,保证任务执行顺序按照任务提交顺序
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SingleThreadExecutor {
public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService ex = Executors.newSingleThreadExecutor();
for(int i = 0;i<5;i++) {
ex.submit(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int j = 0;j<10;j++) {
System.out.println(Thread.currentThread().getName()+" "+j);
}
}
});
}
ex.shutdown();
}
}
3.CashedThreadPool()缓存线程池
可以创建多个线程,数量不固定,线程最大值是int类型的最大值。当没有可用线程时,可以创建新的线程。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CashedThreadPoolTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService ex =Executors.newCachedThreadPool();
for(int i = 0;i<5;i++) {
ex.submit(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int j = 0;j<10;j++) {
System.out.println(Thread.currentThread().getName()+" "+j);
}
}
});
}
ex.shutdown();
//需要执行5次线程任务,根据结果表明,创建了五个线程,5个线程每个都执行一遍for循环
}
}
4.newScheduledThreadPool()创建一个周期性的线程池,支持定时及周期性执行任务
传递的是核心线程数,不是固定线程数。核心线程数是线程池维护的最小线程数,不会被回收
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduleThreadPoolTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName()+"执行"+new Date());
}
}, 5, 3, TimeUnit.SECONDS);
}
}
5.newWorkStealingPool新的线程池类ForkJoinPool扩展
JDK8之后新出的线程池类,之前的线程池类中的线程共享任务队列。在这个线程池中,每一个下次线程都有自己的队列,会造成CPU负载不均衡,可能有一个线程执行的任务过重。当线程发现自己没有任务时,回去其他线程中拿到任务,这样节省了执行任务的时间
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class NewWorkStealingPoolTest {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
System.out.println("--start--");
ExecutorService executorService = Executors.newWorkStealingPool();
for(int i = 0;i<10;i++) {
executorService.submit(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int j = 0;j<5;j++) {
System.out.println(Thread.currentThread().getName()+" "+j);
}
}
});
}
Thread.sleep(3000);//让主线程等待3秒,等子线程执行完任务
System.out.println("--end--");
//如果一个线程分配到了一个很大的任务,会把任务分成多个小任务再分配给各个线程,小任务执行完最后把结果合并
}
}
根据结果表明,每次运行后,创建的线程数是不固定的,可能3个也可能4个
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)