超链接没有反应
551
2022-05-30
一、线程池
首先概括一下线程池的概念,线程池相当于一个包装袋,袋子里有多个线程,在没有任务时,这些线程都是睡眠的,当有任务需要执行某个程序时,会调用相应的线程,被调用的线程会醒,执行过后继续睡眠。系统可以同时调用多个线程。
通过线程池可以启动多线程,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个
Java 培训服务
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。