zoukankan      html  css  js  c++  java
  • 【转载+手写+整理】线程池原理_简单线程池

    一下代码为本人小时候照着网上抄写的,暂时懒得默写一遍,遂记录在此。

    代码中找到了转载出处:https://blog.csdn.net/hsuxu/article/details/8985931


    代码:

    package com.xx.thread;
    
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Queue;
    
    /**
     * 
     * 1、线程池简介:
        多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。   
        假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。
    
        如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能。
                    一个线程池包括以下四个基本组成部分:
                    1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
                    2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
                    3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
                    4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
                   
        线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提高服务器程序性能的。它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。
        线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目,看一个例子:
        假设一个服务器一天要处理50000个请求,并且每个请求需要一个单独的线程完成。在线程池中,线程数一般是固定的,所以产生线程总数不会超过线程池中线程的数目,而如果服务器不利用线程池来处理这些请求则线程总数为50000。一般线程池大小是远小于50000。所以利用线程池的服务器程序不会为了创建50000而在处理请求时浪费时间,从而提高效率。
    
        代码实现中并没有实现任务接口,而是把Runnable对象加入到线程池管理器(ThreadPool),然后剩下的事情就由线程池管理器(ThreadPool)来完成了
     * 
     * 
     * 
     * @author Administrator
     *
     */
    public final class ThreadPool {
    	//线程池中默认个数为5
    	private static int worker_num=5;
    	//工作线程
    	private WorkThread[] workThreads;
    	//未处理的任务
    	/**
    	 * https://www.cnblogs.com/dolphin0520/p/3920373.html
    	 * 一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
    
     	 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
    
      	 2)禁止进行指令重排序。
    	 */
    	private static volatile int finished_task=0;
    	//任务队列,作为缓冲,list不安全
    	private List<Runnable> taskQueue = new LinkedList<Runnable>();
    	
    	private static ThreadPool threadPool;
    	
    	//创建具有默认线程个数的线程池
    	private  ThreadPool(){
    		this(5);
    	}
    	//创建线程池,线程个数为worker_num
    	private  ThreadPool(int worker_num ){
    		ThreadPool.worker_num = worker_num;
    		workThreads = new WorkThread[worker_num];
    		for(int i=0;i<workThreads.length;i++){
    			//创建
    			workThreads[i]= new WorkThread();
    			//开启
    			workThreads[i].start();
    		}
    		
    		
    	}
    	//单例模式,获取一个默认线程个数的线程池
    	public static ThreadPool getThreaPool(){
    		return getThreaPool(ThreadPool.worker_num);
    	}
    	//单例模式,获得一个指定个数的线程池
    	public static ThreadPool getThreaPool(int worker_num1){
    		if(worker_num1<=0){
    			worker_num1 = ThreadPool.worker_num; 
    		}
    		if(threadPool==null){
    			threadPool= new ThreadPool(worker_num1);
    		}
    		return threadPool;
    	}
    	//执行任务,把任务加入任务队列,执行由线程池管理决定
    	public void execute(Runnable task){
    		synchronized (taskQueue) {
    			taskQueue.add(task);
    			taskQueue.notify();//>>
    		}
    	}
    	public void execute(Runnable[] task){
    		synchronized (taskQueue) {
    			for (Runnable t : task) 
    			taskQueue.add(t);
    			taskQueue.notify();//>>
    		}
    	}
    	public void execute(List<Runnable> task){
    		synchronized (taskQueue) {
    			for (Runnable t : task) 
    			taskQueue.add(t);
    			taskQueue.notify();//>>
    		}
    	}
    	//销毁线程池,该方法保证所有任务都完成的情况下蔡晓辉所有线程,否则等待所有任务都完成时在进行销毁
    	public void destory(){
    		while(!taskQueue.isEmpty()){//如果有任务尚未完成,等待一下,?????
    			try {
    				Thread.sleep(10);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			
    		}
    		//工作线程停止工作,置空
    		for(int i=0;i<worker_num;i++){
    			workThreads[i].stopWorker();//执行完任务才会停止
    			workThreads[i]=null;
    		}
    		threadPool=null;
    		taskQueue.clear();
    		
    		
    	}
        // 返回工作线程的个数  
        public int getWorkThreadNumber() {  
            return worker_num;  
        }  
      
        // 返回已完成任务的个数,这里的已完成是只出了任务队列的任务个数,可能该任务并没有实际执行完成  
        public int getFinishedTasknumber() {  
            return finished_task;  
        }  
      
        // 返回任务队列的长度,即还没处理的任务个数  
        public int getWaitTasknumber() {  
            return taskQueue.size();  
        }  
      
        // 覆盖toString方法,返回线程池信息:工作线程个数和已完成任务个数  
        @Override  
        public String toString() {  
            return "WorkThread number:" + worker_num + "  finished task number:"  
                    + finished_task + "  wait task number:" + getWaitTasknumber();  
        }  
    	
    	
    	/**
    	 * 内部类,工作线程
    	 */
    	private class WorkThread extends Thread{
    		//县城是否有效,用于结束线程
    		private boolean isRunning = true;
    		@Override
    		public void run() {
    			Runnable r = null;
    			while(isRunning){//线程无效则丢弃线程
    				synchronized ( taskQueue) {//代码块方式对同步资源上锁
    					while(isRunning&& taskQueue.isEmpty()){//队列为空
    						try {
    							taskQueue.wait(20);//线程等待状态,调用notify会唤醒一个
    						} catch (InterruptedException e) {
    							e.printStackTrace();
    						}
    						if(!taskQueue.isEmpty()){
    							r=taskQueue.remove(0);//取出一元素
    						}
    					if(r!=null){
    						r.run();
    					}
    					finished_task++;
    					r=null;		
    					}
    					
    				}
    			}
    		}
    		
    		//停止工作,让线程自然执行run方法,自然结束1
    		public void stopWorker(){
    			isRunning = false;
    		}
    		
    	}
    
    }
    

  • 相关阅读:
    csuoj 1391: Boiling Vegetables
    csuoj 1392: Number Trick
    nyist 78 圈水池
    1393: Robert Hood 旋转卡壳 凸包
    模板 旋转卡壳 凸包
    模板 凸包 旋转卡壳
    ASP.NET Web API2返回值处理流程
    DependencyInjection源码解读之ServiceProvider
    深入研究EF Core AddDbContext 引起的内存泄露的原因
    私有云方案——利用阿里云云解析实现DDNS
  • 原文地址:https://www.cnblogs.com/the-fool/p/11054175.html
Copyright © 2011-2022 走看看