java中的线程池

Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或者并发执行任务的程序都可以使用线程池。
具体的使用场景:
举例分析

使用线程池的好处

降低资源消耗 创建和销毁线程需要消耗资源,线程池可以重复利用已创建的线程,减少资源消耗。

提高响应速度 创建线程需要时间,当任务到达时,立即执行,无需等待线程创建,这样可以节省时间,提高响应速度。

提高线程的可管理性 线程的创建、销毁、控制管理、调优等都交由线程池统一管理和分配。

线程池的实现原理

线程池的处理流程

核心线程池(corePool)
工作队列(BlockingQueue)
线程池(maximumPool)

向线程池提交一个任务后
1、线程池先判断corePool中的线程是否都在执行任务,即判断当前运行的线程数与corePoolSize的大小,如果小于,则创建新的线程来执行任务(注意,执行这一步要获取全局锁)。否则进入下一步。

2、线程池判断工作队列是否已经满,如果没有满,则将新提交的任务存储在这个工作队列里。否则进入下一步。

3、线程池判断线程池的线程是否都处于工作状态,即判断即判断当前运行的线程数与maximumPoolSize的大小,如果小于,则创建新的线程来执行任务(注意,执行这一步要获取全局锁)。否则,则交给饱和策略来处理,即任务被拒绝,调用RejectedExecutionHandler.rejectedExecution()方法。

线程池的使用

线程池的创建
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);
    }
参数分析:

corePoolSize 线程池的基本大小
当提交一个任务到线程池时,线程池就会创建一个线程来执行任务。这里要注意的是,只要corePoolSize没有达到最大值,即使线程池中存在空闲线程,线程池还是会创建新线程来执行任务。等到需要执行的任务数大于线程池的基本大小时就不再创建。

workQueue 工作队列
用于保存等待执行的任务的阻塞队列。可以选择的阻塞队列有:
ArrayBlockingQueue
LinkedBlockingQueue
SynchronousQueue
PriorityBlockingQueue

maximumPoolSize 线程池最大数量
如果队列满了,但已创建的线程数小于最大线程数,则线程池会创建新的线程来执行任务。但如果工作队列使用了无界的队列,则这个参数就没用了。

defaultHandler

 private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

代码中可以看出饱和策略默认是AbortPolicy,表示无法处理新任务时抛出异常

向线程池提交任务

execute()
用于提交不需要返回值的任务。因为没有返回值,所以无法判断任务是否被线程池执行成功。
源码

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to start a new thread with the given command as its first task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add threads when it shouldn't, by returning false.
         *
         * 2. If a task can be successfully queued, then we still need to double-check whether we should have added a thread (because existing ones died since last checking) or that the pool shut down since entry into this method. So we recheck state and if necessary roll back the enqueuing if stopped, or start a new thread if there are none.
         *
         * 3. If we cannot queue task, then we try to add a new thread.  If it fails, we know we are shut down or saturated and so reject the task.
         */
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    }

submit() 用于提交需要返回值的任务。

public class ThreadPoolExecutor extends AbstractExecutorService {
}
public abstract class AbstractExecutorService implements ExecutorService {
    ...
    ...
    ...
    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }
    ...
    ...
    ...
}
Future<Object> future = executor.submit(returnValueTask);
try{
    Object s = future.get();

}catch(InterruptedException e){

}catch(ExecutionException e){

}finally{

}

线程池返回一个Future类型对象,通过这个Future对象可以判断任务是否执行成功,并且可以通过future.get()方法来回去返回的值。get方法会阻塞当前线程,直到任务完成,而使用get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候可能任务还没有完成。

关闭线程池
线程池的监控
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值