因为创建线程是一个非常消耗资源的情况,线程也是一个重量级的对象,避免频繁的创建和销毁

为了高效的利用线程,出现了线程池这种技术

线程池和一般的资源池不一样,资源池只需要用accqure()获取资源,使用完成利用release()释放资源,Java对于线程池可没这样的提供方法

线程池在本质上来说,采用了生产者-消费者模式

线程的使用方式生产者,生产任务,线程池就是消费者,消费任务

//简化的线程池,仅用来说明工作原理

class MyThreadPool{

//利用阻塞队列实现生产者-消费者模式

BlockingQueue<Runnable> workQueue;

//保存内部工作线程

List<WorkerThread> threads

= new ArrayList<>();

// 构造方法

MyThreadPool(int poolSize,

BlockingQueue<Runnable> workQueue){

this.workQueue = workQueue;

// 创建工作线程

for(int idx=0; idx<poolSize; idx++){

WorkerThread work = new WorkerThread();

work.start();

threads.add(work);

}

}

// 提交任务

void execute(Runnable command){

workQueue.put(command);

}

// 利用多个工作线程负责消费任务,并执行任务

class WorkerThread extends Thread{

public void run() {

//循环取任务并执行

while(true){ ①

Runnable task = workQueue.take();

task.run();

}

}

}

}

/** 下面是使用示例 **/

// 创建有界阻塞队列

BlockingQueue<Runnable> workQueue =

new LinkedBlockingQueue<>(2);

// 创建线程池

MyThreadPool pool = new MyThreadPool(

10, workQueue);

// 提交任务

pool.execute(()->{

System.out.println(“hello”);

});

在整个线程池的内部,维护了一个工作队列,在其中保存了内部的工作线程

然后创建一个集合保存,所有的工作线程,在实际使用过程中,就是提交任务就是保存到队列中

在工作线程之中,就是不断的从队列中拉取任务并且执行

在java中,提供的线程池其实现可以为ThreadPoolExecutor,通过其可以生成需要的指定线程池,其构造函数为

ThreadPoolExecutor(

int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

上述的参数分别为

corePoolSize为核心线程数,为必须保留的线程数

maximumPoolSize 为最大线程数,为最大的可以用的线程数

keepAliveTime 为留存时间,即为一个线程空闲之后可以存活多久

workQueue 工作队列

threadFactory 生产线程的工厂类

handler:可以指定的拒绝策略,提供的拒绝策略有四种

CallerRunsPolicy:提交任务的线程自己去执行

AbortPolicy :直接throws RejectedExectionException

DiscardPolicy 直接丢弃任务

DiscardOldestPolicy 丢弃最老的任务,把新任务加入到队列

后续也支持了allowCoreThreadTimeOut(boolean Value)的设置,也就是corePoolSize中的线程,在超过时间空闲后也撤走

对于java自带的工具类Executors来说,生成的线程池不推荐使用,大多数都是无界的工作队列或者线程池,容易出现OOM的情况

发表评论

邮箱地址不会被公开。 必填项已用*标注