html5 购物网站,网页设计代表性案例,产品项目开发流程图,阿里巴巴做外贸流程1、线程池 线程池就是一个可以复用线程的技术。
2、应用场景 用户每发起一个请求#xff0c;后台就需要创建一个新线程来处理#xff0c;下次新任务来了肯定又要创建新线程处理的#xff0c;而创建新线程的开销是很大的#xff0c;并且请求过多时#xff0c;肯定会产生大…1、线程池 线程池就是一个可以复用线程的技术。
2、应用场景 用户每发起一个请求后台就需要创建一个新线程来处理下次新任务来了肯定又要创建新线程处理的而创建新线程的开销是很大的并且请求过多时肯定会产生大量的线程出来这样会严重影响系统的性能。
3、线程池工作原理
从工作队列中获取一个任务执行任务然后返回线程池并等待下一个任务。 4、创建线程池 java在jdk5.0起提供了代表线程池的接口ExecutorService。
方式一使用ExecutService的实现类ThreadPoolExecutor自创建一个线程池对象。方式二使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象。 4.1、ThreadPoolExecutor ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueRunnable workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) 参数说明
参数一corePoolSize指定线程池的核心线程数量。参数二maximumPoolSize指定线程池的最大线程数量。参数三keepAliveTime指定临时线程的存活时间。参数四unit指定临时线程存活的时间单位秒分时天参数五workQueue指定线程池的任务队列参数六threadFactory指定线程池的线程工厂参数七handler指定线程池的任务拒绝策略线程都在忙任务队列也满了的时候新任务来了怎么处理
//1、通过ThreadPoolExecutor来创建线程池ThreadPoolExecutor pool new ThreadPoolExecutor(3, 5, 8,TimeUnit.SECONDS, new ArrayBlockingQueue(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()); 注意事项
1、临时线程什么时候创建 新任务提交时发现核心线程都在忙任务队列也满了并且还可以创建临时线程此时才会创建临时线程。
2、什么时候开始会拒绝新任务 核心线程和临时线程都在忙任务队列也满了新的任务过来的时候才会开始拒绝任务。
方法名称说明void execute(Runnable command)执行Runnable任务FutureT submit(CallableT task)执行Callable任务返回未来任务对象用于获取线程返回的结果void shutdown()等全部任务执行完毕后再关闭线程池ListRunnable shutdownNow()立刻关闭线程池停止正在执行的任务并返回队列中未执行的任务
5、线程池处理Runnable任务
public class ThreadPoolTest1 {public static void main(String[] args) {//1、通过ThreadPoolExecutor来创建线程池ThreadPoolExecutor pool new ThreadPoolExecutor(3, 5, 8,TimeUnit.SECONDS, new ArrayBlockingQueue(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());MyRunnable myRunnable new MyRunnable();//线程池会自动创建一个新线程自动处理这个任务自动执行的pool.execute(myRunnable);//线程池会自动创建一个新线程自动处理这个任务自动执行的pool.execute(myRunnable);//线程池会自动创建一个新线程自动处理这个任务自动执行的pool.execute(myRunnable);//复用前面的核心任务pool.execute(myRunnable);//复用前面的核心任务pool.execute(myRunnable);//增加线程超出任务队列
// pool.execute(myRunnable);
// pool.execute(myRunnable);//线程池中的三个主线程已经被占用线程队列已满//此时再创建线程就会创建临时线程
// pool.execute(myRunnable);//等线程任务结束后关闭线程池pool.shutdown();//立即关闭线程池
// pool.shutdownNow();}
}public class MyRunnable implements Runnable{Overridepublic void run() {System.out.println(Thread.currentThread().getName()666);try {Thread.sleep(2000);//设置休眠时间便于查看
// Thread.sleep(Integer.MAX_VALUE);//设置最大时间用来测试临时线程的创建} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
执行结果
pool-1-thread-1666
pool-1-thread-3666
pool-1-thread-2666
pool-1-thread-1666
pool-1-thread-2666
5.1、临时线程创建时机
public class ThreadPoolTest1 {public static void main(String[] args) {//1、通过ThreadPoolExecutor来创建线程池ThreadPoolExecutor pool new ThreadPoolExecutor(3, 5, 8,TimeUnit.SECONDS, new ArrayBlockingQueue(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());MyRunnable myRunnable new MyRunnable();//线程池会自动创建一个新线程自动处理这个任务自动执行的pool.execute(myRunnable);//线程池会自动创建一个新线程自动处理这个任务自动执行的pool.execute(myRunnable);//线程池会自动创建一个新线程自动处理这个任务自动执行的pool.execute(myRunnable);//复用前面的核心任务pool.execute(myRunnable);//复用前面的核心任务pool.execute(myRunnable);//增加线程超出任务队列pool.execute(myRunnable);pool.execute(myRunnable);//线程池中的三个主线程已经被占用线程队列已满//此时再创建线程就会创建临时线程pool.execute(myRunnable);//等线程任务结束后关闭线程池
// pool.shutdown();//立即关闭线程池
// pool.shutdownNow();}
}
public class MyRunnable implements Runnable{Overridepublic void run() {System.out.println(Thread.currentThread().getName()666);try {
// Thread.sleep(2000);//设置休眠时间便于查看Thread.sleep(Integer.MAX_VALUE);//设置最大时间用来测试临时线程的创建} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
执行结果会创建临时线程4
pool-1-thread-1666
pool-1-thread-3666
pool-1-thread-2666
pool-1-thread-4666
如果再加一个就会创建临时线程5
pool-1-thread-2666
pool-1-thread-4666
pool-1-thread-3666
pool-1-thread-1666
pool-1-thread-5666
再增加一个就会超出线程池的限定此时就会按照设置的方法进行处理
参数七handler指定线程池的任务拒绝策略线程都在忙任务队列也满了的时候新任务来了怎么处理
新任务拒绝策略
策略详解 ThreadPoolExecutor.AbortPolicy() 不执行此任务而且直接抛出一个运行时异常 ThreadPoolExecutor.DiscardPolicy() 新任务被提交后直接被丢弃掉并且不会抛出异常无法感知到这个任务会被丢弃可能造成数据丢失。 ThreadPoolExecutor.DiscardOldestPolicy() 会丢弃任务队列中的头结点通常是存活时间最长并且未被处理的任务。 ThreadPoolExecutor.CallerRunsPolicy() 当有新任务提交后如果线程池没被关闭且没有能力执行则把这个任务交于提交任务的线程执行也就是谁提交任务谁就负责执行任务。不会抛出异常。
6、线程池处理Callable任务
public class ThreadPoolTest2 {public static void main(String[] args) throws ExecutionException, InterruptedException {//1、通过ThreadPoolExecutor来创建线程池ThreadPoolExecutor pool new ThreadPoolExecutor(3, 5, 8,TimeUnit.SECONDS, new ArrayBlockingQueue(4), Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());Future f1 pool.submit(new MyCallable(100));Future f2 pool.submit(new MyCallable(200));Future f3 pool.submit(new MyCallable(300));Future f4 pool.submit(new MyCallable(400));System.out.println(f1.get());System.out.println(f2.get());System.out.println(f3.get());System.out.println(f4.get());}
}public class MyCallable implements Callable {private int n;public MyCallable(int n) {this.n n;}Overridepublic String call() throws Exception {int sum 0;for (int i 1; i n; i) {sum i;}return Thread.currentThread().getName()求出了1-n的和是 sum;}
}
执行结果
pool-1-thread-1求出了1-100的和是5050
pool-1-thread-2求出了1-200的和是20100
pool-1-thread-3求出了1-300的和是45150
pool-1-thread-3求出了1-400的和是80200
7、Executors工具类实现线程池
方法名称说明newFixedThreadPool(int nThreads)创建固定数量线程的线程池如果某个线程因为执行异常而结束那么线程池会补充一个新线程替代它。newSingleThreadExecutor() 创建只有一个线程的线程池对象如果改线程出现异常而结束那么线程池会补充一个新线程。 newCachedThreadPool线程数量随着人物增加而增加如果线程任务执行完毕且空闲了60秒则会被回收掉newScheduledThreadPool创建一个线程池可以实现在给定的延迟后运行任务或者定期执行任务
public class ThreadPoolTest3 {public static void main(String[] args) throws ExecutionException, InterruptedException {//1、通过ThreadPoolExecutor来创建线程池
// ThreadPoolExecutor pool new ThreadPoolExecutor(3, 5, 8,
// TimeUnit.SECONDS, new ArrayBlockingQueue(4), Executors.defaultThreadFactory(),
// new ThreadPoolExecutor.CallerRunsPolicy());// ExecutorService pool Executors.newFixedThreadPool(3);
// ExecutorService pool Executors.newSingleThreadExecutor();
// ExecutorService pool Executors.newCachedThreadPool();ScheduledExecutorService pool Executors.newScheduledThreadPool(5);Future f1 pool.submit(new MyCallable(100));Future f2 pool.submit(new MyCallable(200));Future f3 pool.submit(new MyCallable(300));Future f4 pool.submit(new MyCallable(400));System.out.println(f1.get());System.out.println(f2.get());System.out.println(f3.get());System.out.println(f4.get());}
}
8、核心线程数的配置
计算密集型的任务核心线程数量CPU核数 1IO密集的任务核心数量CPU核数 * 2
9、不建议使用Executors创建线程池 缺乏对线程池的精细控制Executors 提供的方法通常创建一些简单的线程池如固定大小的线程池、单线程线程池等。然而这些线程池的配置通常是有限制的难以进行进一步的定制和优化。 可能引发内存泄漏一些 Executors 创建的线程池特别是 FixedThreadPool 和 SingleThreadExecutor使用无界队列来存储等待执行的任务。这意味着如果任务提交速度远远快于任务执行速度队列中可能会积累大量未执行的任务可能导致内存泄漏。 不易处理异常Executors 创建的线程池默认使用一种默认的异常处理策略通常只会将异常打印到标准输出或记录到日志中但不会提供更多的控制。这可能导致异常被忽略或无法及时处理。 不支持线程池的动态调整某些线程池应该支持动态调整线程数量以应对不同的负载情况。Executors 创建的线程池通常是固定大小的不容易进行动态调整。 可能导致不合理的线程数目一些 Executors 方法创建的线程池默认将线程数目设置为非常大的值这可能导致系统资源的浪费和性能下降。
因此对于生产环境中的应用程序通常建议使用 ThreadPoolExecutor 类直接创建和配置线程池以便更精确地控制线程池的各个参数包括核心线程数、最大线程数、队列类型、拒绝策略等。这样可以更好地满足应用程序的需求并确保线程池在不同负载情况下表现良好。当然在某些情况下Executors 创建的简单线程池可能足够使用但需要谨慎考虑其限制和适用性。