java多线程 线程池的使用
java线程池
- 说明
- 实例
- 总结
说明
目前大家有在使用的,例如数据库连接池等其他的池技术,可以有效使用资源,方便控制,线程池也是如此,目前线程的使用都是从线程池,很少自己单独创建,维护线程的使用。
实例
package com.example.demo.pool;
import java.util.Date;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class PoolTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ThreadPoolExecutor pool = new ThreadPoolExecutor(10,20,6,TimeUnit.SECONDS,new ArrayBlockingQueue(20),new ThreadPoolExecutor.CallerRunsPolicy());
for(int i = 0 ;i<3;i++) {
Runnable work = new MyThreadTest();
pool.execute(work);
}
for(int i = 0 ;i<3;i++) {
Callable work1 = new MyThreadCallTest();
Future future = pool.submit(work1);
System.out.println("接收到的参数:"+ String.valueOf(future.get()));
}
}
}
class MyThreadTest implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
//synchronized (MyThreadTest.class) {
System.out.println("当前的Call流程:"+Thread.currentThread().getName()+"开始"+new Date());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("当前的Call流程:"+Thread.currentThread().getName()+"结束"+new Date());
//}
}
}
class MyThreadCallTest implements Callable<String>{
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
//synchronized (MyThreadCallTest.class) {
System.out.println("当前的流程:"+Thread.currentThread().getName()+"开始"+new Date());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("当前的流程:"+Thread.currentThread().getName()+"结束"+new Date());
// }
return Thread.currentThread().getName()+"返回结果";
}
}
总结
降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的资源浪费。
提高响应速度。当任务到达时,不需要等到线程创建就能立即执行。
方便管理线程。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以对线程进行统一的分配,优化及监控。
参数 corePoolSize
表示线程池的常驻核心线程数。如果设置为 0,则表示在没有任何任务时,销毁线程池;如果大于 0,即使没有任务时也会保证线程池的线程数量等于此值;
应该结合实际业务设置此值的大小。若 corePoolSize 的值较小,则会出现频繁创建和销毁线程情况;若值较大,则会浪费系统资源。参数 maximumPoolSize
表示线程池最大可以创建的线程数。官方规定此值必须大于 0,也必须大于等于 corePoolSize 的值;
此值只有在任务比较多,且不能存放在任务队列时,才会用到。参数 keepAliveTime
表示线程的存活时间。当线程池空闲时并且超过了此时间,多余的线程就会销毁,直到线程池中的线程数等于 corePoolSize 的值为止;
若 maximumPoolSize 的值 等于 corePoolSize 的值,则线程池在空闲的时候不会销毁任何线程。参数 unit
表示存活时间的单位,配合 keepAliveTime 参数共同使用。
参数 workQueue
表示线程池执行的任务队列;
当线程池的所有线程都在处理任务时,若来了新任务则会缓存到此任务队列中,然后等待执行。参数 threadFactory
表示线程的创建工厂,一般使用默认的线程创建工厂的方法 Executors.defaultThreadFactory()来创建线程。
参数 RejectedExecutionHandler
表示指定线程池的拒绝策略,属于一种限流保护的机制;
当线程池的任务已经在缓存队列 workQueue 中存满了之后,并且不能创建新的线程来执行此任务时,就会用到此拒绝策略
四种拒绝策略
(1) AbortPolicy: 丢弃任务并抛出异常。
(2) DiscardPolicy:丢弃任务但不抛出异常。
(3) DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务
(4) CallerRunsPolicy:由调用线程处理该任务submit() 方法可以配合 Future来接收线程执行的返回值,而 execute() 不能接收返回值;
execute() 方法属于 Executor 接口的方法,而 submit() 方法则是属于 ExecutorService 接口的方法。
还没有评论,来说两句吧...