关于线程池的一些概念

  • 线程池概念与作用

    • 为什么需要线程池(池化资源技术产生原因)

      解决线程生命周期开销问题和资源不足问题。消除线程创建带来的延迟,使应用程序响应更快。

    • 一个比较简单的线程池构成

      1. 线程池管理器
        -创建、销毁并管理线程池,将工作线程放入线程池
      2. 工作线程
        -一个可以循环执行任务的线程,没有任务时等待
      3. 任务队列
        -提供缓冲机制,将没有处理的任务放入任务队列中
      4. 任务接口
        -每个任务必须实现的接口,主要规定任务入口、任务执行完后的收尾工作、任务的执行状态等,工作线程通过该接口调度任务的执行。
  • 实现基础的线程池 一个工作线程 一个调度器

    • 一个简单的工作线程 和一个 简单的线程池调度器
package com.qinhan.threadingThreadPool;
//执行线程:这是我们的工作线程
public class ExecutorThread extends Thread {
	//用于描述线程是否处于运行状态。
	boolean runningFlag=false;
	private Runnable callBack=null;
	public void setCallBack(Runnable callBack) {
		this.callBack=callBack;
	}
	public synchronized void setRunning(boolean flag) {
		runningFlag=flag;
		if(flag) {
			//如果flag为true说明希望执行线程处理某一个具体的任务,则唤醒某个线程。
			this.notify();
		}
	}
	public synchronized void run() {
		try {
			while(true) {
				//任务执行结束后阻塞本线程
				if(!runningFlag) {
					this.wait();
				}else {
					callBack.run();
					setRunning(false);
				}
			}
		}catch (Exception e) {
			// TODO: handle exception
		}
	}
}

package com.qinhan.threadingThreadPool;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ThreadPoolExecutor {
	//池容器
	private List<ExecutorThread> threads;
	//构造方法:创建指定数量的线程并启动并将其放入池容器。
	private ThreadPoolExecutor(int threadCount) {
		threads=Collections.synchronizedList(new ArrayList<ExecutorThread>());
		for(int i=1;i<=threadCount;i++) {
			ExecutorThread thread=new ExecutorThread();
			threads.add(thread);
			thread.start();
		}
	}
	//从线程池中选择一个空闲的线程执行任务
	public void execute(Runnable callBack) {
		int i;
		for(i=0;i<threads.size();i++) {
			ExecutorThread currentThread=threads.get(i);
			if(!currentThread.runningFlag) {
				currentThread.setCallBack(callBack);
				currentThread.setRunning(true);
				return;
			}
		}
		if(i==threads.size()) {
			System.out.println("线程资源已经用完,请稍等片刻再申请资源");
		}
	}
}

  • 线程池调度器

    • Executor :JDK5的异步框架

      • 作用:将任务提交和任务执行进行解耦;使得开发人员不再关注各类任务线程的实现,而将后台异步执行的内容抽象为单个任务。执行任务的人只需把Task描述清除后提交即可。

        流程:提交Callable对象给ExecutorService(如常用的线程池ThreadPoolExecutor),得到一个Future对象,调用Future对象的get()等待执行结果。
        
      • Executor框架的重要核心接口和类

        • Executor接口 :
          1. 一个可提交可执行任务的工具
          2. 解耦任务提交和任务执行
          3. 主要替代显示的创建和运行线程
        • ExecutorService接口
          1. 提供异步的管理一个或多个线程终止、执行过程(Future)的方法
          2. 和其实现类提供简便的方式提交任务并获取任务执行结果,封装任务执行的全部过程。
        • ScheduledExecutorService接口
        • 主要工具类 Executors用来获取实现ExecutorService接口的子类
          1. 提供一系列工厂方法用于创建任务执行器,返回的任务执行器都实现ExecutorService接口(且绝大部分执行器都完成池化操作。)
    • 生成ExecutorService实现类 内置的常见工厂方法及生成的任务调度器特征 步骤1

      // Executors类的静态方法 获取 ExecutorService实现类
      ExecutorService newFixedThreadPool(int nThreads) //创建固定数目线程的线程池
      ExecutorService newCachedThreadPool()	//创建一个可缓存的线程池
      ExecutorService newSingleThreadExecutor()  //创建一个单线程化的Exrcutor  保证线程顺序执行
      ScheduledExecutorService newScheduledThreadPool(int corePoolSize)//创建一个支持定时及周期性的人物执行的线程池,多数情况可用来替代Timer类。
      
      • ExecutorService的方法 步骤2
      • execute(Runnable)
        • 异步方式执行,无法获取返回结果
      • submit(Runnable)
        • 返回一个Future对象,该对象可以判断Runnable任务是否结束执行。
      • submit(Callable)
        • Callable可以返回一个结果
        • 返回值同样从该方法返回的Future对象中获取。
      • invokeAny(…)
        • 参数:接收一个包含Callable对象的集合
        • 返回值:返回集合中某个Callable的结果,而且无法保证调用之后返回的结果是集合中的哪个Callable结果。看自写的代码。
        • 如果一个任务运行完毕或抛出异常,方法会取消其他Callable的执行。也就是找到一个东西,那么不需要再找了。
      • invokeAll(…)
        • 参数:Callable对象集合
        • 返回值:返回一个包含Future对象的集合,可通过该集合管理每一个Callable的执行结果。找出所有东西
        • 注意:任务可能因为异常而导致运行结束,所以它可能不是真的成功运行。而这个我们无法通过Future对象来了解这个差异。
    • 关闭ExecutorService 步骤3

      • 使用完毕,我们应该关闭它,保证其中的线程不会继续保持运行状态
      • 场景一:如果程序通过main主线程启动,主线程退出,但还有一个活动的ExecuterService存在于程序中;思考:会如何? 解答:程序将继续保持运行状态。存在于ExecutorService中的活动线程会阻止JVM关闭。
      • shutdown方法:关闭ExecutorService中的线程;注意:它并不会马上关闭,而是不再接收新的任务,一旦所有线程结束执行当前任务,它才会真的关闭。而所有在shutdown方法前提交到ExecutorService的任务都会执行。
      • shutdownNow方法:希望立即关闭ExecutorService。注意:尝试马上关闭所有正在执行的任务,并且跳过所有已经提交但是还没有运行的任务。对于正在执行的任务,是否能够成功关闭是无法保证的。
  • Runnable与Callable

    • 区别:前者方法为run,不返回任何任务。后者方法为call,返回执行后的结果。
    • 都符合函数式接口的标准
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值