精华内容
下载资源
问答
  • 设计模式-线程池模式
    千次阅读
    2019-04-03 08:27:01

     

    定义:

    Worker Thread,一般都称为线程池。该模式事先启动一定数目的工作线程。当没有请求工作的时候,所有的工人线程都会等待新的请求过来,一旦有工作到达,就马上从线程池中唤醒某个线程来执行任务,执行完毕后继续在线程池中等待任务池的工作请求的到达。

    • 任务池:主要是存储接受请求的集合,利用它可以缓冲接受到的请求,可以设置大小来表示同时能够接受最大请求数目。这个任务池主要是供线程池来访问。
    • 线程池:这个是工作线程所在的集合,可以通过设置它的大小来提供并发处理的工作量。对于线程池的大小,可以事先生成一定数目的线程,根据实际情况来动态增加或者减少线程数目。线程池的大小不是越大越好,线程的切换也会耗时的。

    Worker Thread的角色:

    • Client参与者,发送Request的参与者
    • Channel参与者,负责缓存Request的请求,初始化启动线程,分配工作线程
    • Worker参与者,具体执行Request的工作线程
    • Request参与者

    实例应用

    利用同步块来处理,Vector容器来存储客户端请求。利用Vector来存储,依旧是每次集合的最后一个位置添加请求,从开始位置移除请求来处理。在Channel有缓存请求方法和处理请求方法,利用生成者与消费者模式来处理存储请求,利用正向等待来判断任务池的非空状态。

    代码实现:

    public class Channel {
        public final static int THREAD_COUNT=4;
        public static void main(String[] args) {
    
          //注意:Map不是Collection的子类,都是java.util.*下的同级包
          Vector pool=new Vector();
          //工作线程,初始分配一定限额的数目
          WorkerThread[] workers=new WorkerThread[THREAD_COUNT];
                              
          //初始化启动工作线程
          for(int i = 0; i < workers.length; i++)
          {
              workers[i] = new WorkerThread(pool);
              workers[i].start();
          }
                               
          //接受新的任务,并且将其存储在Vector中
          Object task = new Object();//模拟的任务实体类
          //此处省略具体工作
          //在网络编程中,这里就是利用ServerSocket来利用ServerSocket.accept接受一个Socket从而唤醒线程
                               
          //当有具体的请求达到
          synchronized(pool)
          {
              pool.add(pool.size(), task);
              pool.notifyAll();//通知所有在pool wait set中等待的线程,唤醒一个线程进行处理
          }
          //注意上面这步骤添加任务池请求,以及通知线程,都可以放在工作线程内部实现
          //只需要定义该方法为static,在方法体用同步块,且共享的线程池也是static即可
                               
          //下面这步,可以有可以没有根据实际情况
          //取消等待的线程
          for(int i = 0; i < workers.length; i++)
          {
              workers[i].interrupt();
          }
        }
    }

    这个主要的作用如下

    • 缓冲客户请求线程(利用生产者与消费者模式)
    • 存储客户端请求的线程
    • 初始化启动一定数量的线程
    • 主动来唤醒处于任务池中wait set的一些线程来执行任务

    定义两个集合,一个是存放客户端请求的,利用Vector;一个是存储线程的,就是线程池中的线程数目。
    Vector是线程安全的,它实现了Collection和List,可以实现可增长的对象数组。
    与数组一样,它包含可以使用整数索引进行访问的组件。但Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。

    Collection中主要包括了list相关的集合以及set相关的集合,Queue相关的集合。

    public class WorkerThread extends Thread {
        private List pool;//任务请求池
        private static int fileCompressed = 0;//所有实例共享的
                         
        public WorkerThread(List pool)
        {
              this.pool = pool; 
        }
                         
        //利用静态synchronized来作为整个synchronized类方法,仅能同时一个操作该类的这个方法
        private static synchronized void incrementFilesCompressed()
        {
            fileCompressed++;
        }
                         
        public void run()
        {
            while(true)
            {
                synchronized(pool)
                {
                    //利用多线程设计模式中的
                    //Guarded Suspension Pattern,警戒条件为pool不为空,否则无限的等待中
                    while(pool.isEmpty())
                    {
                        try{
                            pool.wait();//进入pool的wait set中等待着,释放了pool的锁
                        }catch(InterruptedException e)
                        {
                        }
                    }                                 
                    pool.remove(0);//获取任务池中的任务,并且要进行转换
                }
                //下面是线程所要处理的具体工作
            }
        }
    }

    在保证无限循环等待时,通过共享互斥来访问pool变量。当线程被唤醒,需要重新获取pool的锁,再次执行synchronized代码块中其余的工作;当不为空的时候,继续再判断是否为空,如果不为空,则跳出循环。必须先从任务池中移除一个任务来执行,统一用从末尾添加,从开始处移除

    总结

    线程池模式在实际编程中应用的很多,如数据库连接池,socket长连接等等。通过一定数量的工作者线程去执行不断被提交的任务,节约了线程这种有限且昂贵的资源。该模式有以下几个好处:

    • 抵消线程创建的开销,提高响应性
    • 封装了工作者线程生命周期管理
    • 减少销毁线程的开销

    但是要用好线程池模式,还需要考虑如下的问题:

    • 工作队列的选择:通常有三种队列方式,有界队列(BoundedQueue)工作队列本身并不限制线程池中等待运行的任务的数量,但工作队列中实际可容纳的任务取决于任务本身对资源的使用情况;无界队列(UnboundQueue)工作队列限定线程池中等待大量的数量,在一定程度上可以限制资源的消耗;直接交接队列(SymchrinousQueue)不适用缓冲空间内部提交任务的时候调用的是工作队列的非阻塞式入队列方法,所以没有等待队列,会有新的线程对入队列失败的任务进行处理。
    • 线程池大小调参:太大了浪费资源,太大无法充分利用资源,所以线程池大小取决于该线程池所要处理任务的特性,系统资源以及任务锁使用的稀缺资源状况。
    • 线程池监控:线程池的大小,工作队列的容量,线程空闲时间限制这些熟悉的调试过程需要有程序去监控来方便调试ThreadPoolExecutor类提供了监控的方法。
    • 线程泄露:线程池中的工作者线程会意外终止,使得线程池中实际可用的工作者线程减少。出现的原因是线程对象的run方法的异常处理没有捕获RuntimeException和Error导致run方法意外返回,使得相应线程意外终止。所以要注入捕获相应异常。但是还有一种可能情况需要注意,如果线程需要请求外部资源而且对外部资源的请求没有时间限制的话,线程实际上可能已经泄露了。
    • 可靠性和线程池饱和处理策略:工作队列的选择对于线程大小需求变化没有处理方式,所以需要线程饱和处理策略。
    • 死锁:线程请求类似的资源可能形成死锁。
    • 线程池空闲线程清理:过长时间没有进行任务处理的线程是对系统资源的浪费,所以需要相应的处理代码。
    更多相关内容
  • 线程池设计模式

    2019-12-27 22:20:21
    一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个 线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够...

    线程池

    线程池:
           一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个 线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。

    应   用:

    1. 需要大量的线程来完成任务,且完成任务的时间比较短。
    2. 对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
    3. 接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。
     29 class ThreadPool{
     30     private:
     31         int num;
     32         queue<Task> q;
     33         pthread_mutex_t lock;
     34         pthread_cond_t cond;
     
     65     public:
     66         ThreadPool(int num_ = 6)
     67             :num(num_)
     68         {
     69             pthread_mutex_init(&lock, nullptr);
     70             pthread_cond_init(&cond, nullptr);
     71         }
     72         static void *HandlerTask(void* arg)
     73         {
     74             pthread_detach(pthread_self());
     75             ThreadPool *tp = (ThreadPool*) arg;
     76             for(;;)
     77             {
     78                 tp->LockQueue();
     79                 if(tp->IsQueueEmpty())
     80                 {
     81                     tp->PthreadWait();
     82                 }
     83                 Task t;
     84                 tp->PopTask(t);
     85                 tp->UnlockQueue();
     86                 int result = t.Run();
     87                 cout << "Thread: " <<pthread_self()<<", result: "<<result<<<endl;
     88              }
     89         }
      void Init()
     91         {
     92             pthread_t tid;
     93             int i = 0;
     94             for(; i < num ; i++)
     95             {
     96                 pthread_create(&tid, nullptr, HandlerTask, (void*) this);
     97             }
     98         }
    

    注意:类内成员函数多线程调用时需要声明为static形式,因为C++类成员函数使用时,都会隐式传递一个this指针给该函数,this指针指向该类的对象

    懒汉模式

           资源并不在初始化阶段全部加载或者初始化,而是等到使用的时候才去判断。
           优点:初始化比较快,在运行阶段使用的时候也只需要加载一次。
           实现:

    class Test {
    private:
    	static int* data;
    public:
    	int *get_instance()
    	{
    		if (data == NULL)
    		{
    			data = (int*)malloc(4);
    			return data;
    		}
    	}
    };
    

    饿汉模式

           所有的资源加载或者对象实例化都放在程序的初始化阶段,接下来在各个线程中直接使用即可。
           优点:资源直接加载,因此运行时性能会比较高
           缺点:将当前不用的资源加载到内存中,因此资源消耗大,初始化阶段耗时比较长。
           实现:

    class Test {
    private:
    	static int data;
    public:
    	int* get_instance()
    	{
    		return &data;
    	}
    };
    
    展开全文
  • 线程池核心设计与实现、线程池使用了什么设计模式、要你设计的话,如何实现一个线程池

    【重难点】【JUC 05】线程池核心设计与实现、线程池使用了什么设计模式、要你设计的话,如何实现一个线程池

    一、线程池核心设计与实现

    线程池核心实现类是 ThreadPool,下图为 ThreadPoolExcutor 的 UML 类图

    在这里插入图片描述

    ThreadPoolExcutor 实现的顶层接口是 Executor,顶层接口 Excutor 提供了一种思想:将任务提交和任务执行进行解耦。用户无需关注如何创建线程、如何调度线程来执行任务,用户只需要提供 Runnable 对象,将任务的运行逻辑提交到执行器(Executor)中,由 Executor 框架完成线程的调配和任务的执行部分

    ExecutorService 接口增加了一些能力:

    1. 扩充执行任务的能力,补充可以为一个或一批异步任务生成 Future 的方法
    2. 提供了管控线程池的方法,比如停止线程池的运行

    AbstractExecutorService 则是上层的抽象类,将执行任务的流程串联了起来,保证下层的实现只需关注一个执行任务的方法即可

    最下层的实现类 ThreadPoolExecutor 实现最复杂的运行部分,ThreadPoolExecutor 将会一方面维护自身的生命周期,另一方面同时管理线程和任务,使两者良好地结合从何执行并行任务

    ThreadPoolExecutor 的运行机制如下图所示:

    在这里插入图片描述

    线程池在内部实际上构建了一个生产者消费者模型,将线程和任务两者解耦,并不直接关联,从而良好地缓冲任务,复用线程。线程池的运行主要分为两部分:任务管理、县城管理。任务管理部分充当生产者的角色,当任务提交后,线程池会判断该任务后续的流传:

    1. 直接申请线程执行该任务
    2. 缓冲到队列中等待线程执行
    3. 拒绝该任务

    线程管理部分是消费者,它们被同一维护在线程池内,根据任务请求进行线程的分配,当线程执行完任务后则会继续获取新的任务去执行,最终当线程获取不到任务的时候,线程就会被回收

    二、线程池使用了什么设计模式

    数据库连接池、线程池本质上都是连接池技术,连接池技术的核心是让创建的资源复用,通过减少创建和销毁来提升性能

    这正是享元模式的理念,享元模式的目的是实现对象的共享,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用

    FlyWeightFactory 负责创建和管理享元单元,当一个客户端请求时,工厂需要检查当前对象池中是否有符合条件的对象,如果有,就返回已经存在的对象,如果没有,则创建一个新对象

    设计模式详见【设计模式】第四章 工厂模式【设计模式】第七章 享元模式

    三、要你设计的话,如何实现一个线程池

    1.线程池的关键变量

    • 一个存放所有线程的集合
    • 一个任务分配给线程池的时候,线程池可以分配一个线程处理它,当线程池中没有空闲线程时,我们还需要一个队列来存储提交给线程池的任务
    • 初始化一个线程时,要指定这个线程池的大小
    • 我们还需要一个变量来保存已经运行的线程数目
    //存放线程的集合
    private ArrayList<MyThread> threads;
    //任务队列
    private ArrayBlockingQueue<Runnable> taskQueue;
    //线程池初始限定大小
    private int threadNum
    //已经工作的线程数目
    private int workThreadNum;
    

    2.线程池的核心方法

    执行任务

    向线程池提交一个任务时,如果已经运行的线程 < 线程池大小,则创建一个线程运行任务,并把这个线程放入线程池,否则将任务放入缓冲队列中

    public void execute(Runnable runnable){
    	try{
    		mainLock.lock();
    		//线程池未满,每加入一个任务则开启一个线程
    		if(workThreadNum < threadNum){
    			MyThread myThread = new MyThread(runnable);
    			myThread.start();
    			threads.add(myThread);
    			workThreadNum++;
    		}
    		//线程池已满,放入任务队列,等待有空闲线程时执行
    		else{
    			//队列已满,无法添加时,拒绝任务
    			if(!taskQueue.offer(runnable)){
    				rejectTask();
    		}
    	}finally{
    		mainLock.unlock();
    	}
    }
    

    从任务队列中取出任务,分配给线程池中 “空闲” 的线程完成

    很容易想到的思路是额外开启一个线程,时刻监控线程池的线程空余情况,一旦有线程空余,则马上从任务队列取出任务,交付给空余线程完成

    这种思路理解起来很容易,但仔细思考,实现起来非常麻烦。第一,如何检测到线程池中的空闲线程是一个问题。第二,如何将任务交付给一个 .start() 运行状态中的空闲线程。想要实现这两点都不轻松

    所以我们转换一下思维,线程池中的所有线程一直都是运行状态的,线程的空闲只是代表此刻它没有在执行任务而已。一旦运行中的线程没有执行任务,就自己去队列中取任务执行

    为了达到这种效果,我们要重写 run 方法,所以要自定义一个 MyThread 类,把线程都放在这个自定义线程类

    class MyThread extends Thread{
    	private Runnable task;
    
    	public MyThread(Runnable runnable){
    		this.task = runnable;
    	}
    	@Override
    	public void run(){
    		//该线程一直启动着,不断地从任务队列取出任务执行
    		while(true){
    			//如果初始化任务不为空,则执行初始化任务
    			if(task != null){
    				task.run();
    				task = null;
    			}
    			//否则去任务队列取任务并执行
    			else{
    				Runnable queueTask = taskQueue.poll();
    				if(queueTask != null)
    					queueTask.run();
    			}
    		}
    	}
    }
    

    完整代码

    public class MyThreadPool{
    
    	public static void main(String[] args){
    		MyThreadPool myThreadPool = new MyThreadPool(5);
    		Runnable task = new Runnable(){
    			@Override
    			public void run(){
    				System.out.println(Thread.currentThread().getName()+"执行中");
    			}
    		};
    
    		for(int i = 0; i < 20; i++){
    			myThreadPool.execute(task);
    		}
    	}
    
    	//存放线程的集合
    	private ArrayList<MyThread> threads;
    	//任务队列
    	private ArrayBlockingQueue<Runnable> taskQueue;
    	//线程池初始限定大小
    	private int threadNum;
    	//已经工作的线程数目
    	private int workThreadNum;
    
    	private final ReentrantLock mainLock = new ReentrantLock();
    
    	public MyThreadPool(int initPoolNum){
    		threadNum = initPoolNum;
    		threads = new ArrayList<>(initPoolNum);
    		//任务队列初始化为线程池线程数的四倍
    		taskQueue = new ArrayBlockingQueue<>(initPoolNum*4);
    
    		threadNum = initPoolNum;
    		workThreadNum = 0;
    	}
    
    	public void execute(Runnable runnable){
    		try{
    			mainLock.lock();
    			//线程池未满,每加入一个任务则开启一个线程
    			if(workThreadNum < threadNum){
    				MyThread myThread = new MyThread(runnalbe);
    				myThread.start();
    				thread.start();
    				threads.add(myThread);
    				workThreadNum++;
    			}
    			//线程池已满,放入任务队列,等待有空闲线程时执行
    			else{
    				//队列已满,无法添加时,拒绝任务
    				if(!taskQueue.offer(runnable)){
    					rejectTask();
    				}
    			}
    		}finally{
    			mainLock.unlock();
    		}
    	}
    
    	private void rejectTask(){
    		System.out.println("任务队列已满,无法继续添加,请扩大您的初始化线程池");
    	}
    
    	class MyThread extends Thread{
    		private Runnable task;
    
    		public MyThread(Runnable runnable){
    			this.task = runnable;
    		}
    		
    		@Override
    		public void run(){
    			//该线程一直启动着,不断地从任务队列取出任务执行
    			while(true){
    				//如果初始化任务不为空,则执行初始化任务
    				if(task != null){
    					task.run();
    					task = null;
    				}
    				//否则去任务队列取任务并执行
    				else{
    					Runnable queueTask = taskQueue.poll();
    					if(queueTask != null)
    						queueTask.run();
    				}
    			}
    		}
    	}
    }	
    

    总结一下自定义线程池的工作流程:

    1. 初始化线程池,指定线程池大小
    2. 向线程池中放入任务执行
    3. 如果线程池中创建的线程数未满,则创建我们自定义的线程类放入线程池集合,并执行任务。任务完成后该线程会一直监听队列
    4. 如果线程池中创建的线程数已满,则将任务放入缓冲任务队列
    5. 线程池中所有创建的线程都会一直从缓存任务队列中取任务,取到任务后立即执行
    展开全文
  • 文章目录线程池 :单例模式饿汉模式懒汉模式--延时加载 线程池线程池=线程安全队列+一大堆的线程(执行任务的线程) 线程池示例: 创建固定数量线程池,循环从任务队列中获取任务对象, 获取到任务对象后,执行...

    线程池 :

    线程池=线程安全队列+一大堆的线程(执行任务的线程)

    线程池示例:

    1. 创建固定数量线程池,循环从任务队列中获取任务对象,
    2. 获取到任务对象后,执行任务对象中的任务接口

    代码示例:

    #pragma once 
    
    #include <unistd.h>
    #include <math.h>
    #include <pthread.h>
    #include <iostream>
    #include <queue>
    
    #define NUM 5
    
    class Task
    {
      public:
        int base;
    
      public:
        Task()
        {}
    
        Task(int _b)
          :base(_b)
        {}
    
        void Run()
        {
        std::cout << "thread is[" << pthread_self() << "] task run ... done: base# " << base << "pow is# " << pow(base, 2) << std::endl;
        }
    
        ~Task()
        {}
    };
    
    class ThreadPool 
    {
      private:
        std::queue<Task*> q;
        int max_num;//线程总数
        pthread_mutex_t lock;
        pthread_cond_t cond;//让consumer等待
      
      public:
        void LockQueue()
        {
          pthread_mutex_lock(&lock);
        }
    
        void UnlockQueue()
        {
          pthread_mutex_unlock(&lock);
        }
    
        bool IsEmpty()
        {
          return q.size() == 0;
        }
    
        void ThreadWait()
        {
          pthread_cond_wait(&cond, &lock);
        }
    
        void ThreadWakeUp()
        {
          pthread_cond_signal(&cond);//指定唤醒
        }
    
        void ThreadsWakeUP()
        {
          pthread_cond_broadcast(&cond);//唤醒所有
        }
    
      public:
        ThreadPool(int _max=NUM)
          :max_num(_max)
        {}
        
        static void *Routine(void *arg)//内部成员函数带this指针,回调函数一个参数
        {
          ThreadPool *this_p = (ThreadPool*)arg;
          while(true)
          {
            this_p->LockQueue();
            while(this_p->IsEmpty())//没任务就一直等待
            {
             this_p->ThreadWait();
            }
            
            Task t;
            this_p->Get(t);//取任务
            this_p->UnlockQueue();
            t.Run();//执行任务在释放锁后
          }
        }
    
        void ThreadPoolInit()
        {
           pthread_mutex_init(&lock, nullptr);
           pthread_cond_init(&cond, nullptr);
            
           pthread_t t;
           for(int i = 0; i < max_num; ++i)
           {
             pthread_create(&t, nullptr, Routine, this);
           }
        }
        
        //外部server放任务
        void Put(Task &in)
        {
          LockQueue();
          q.push(&in);//塞任务
          UnlockQueue();
    
          ThreadWakeUp();
        }
        
        //内部ThreadPool执行任务
        void Get(Task &out)
        {
          Task *t = q.front();
          q.pop();
          out = *t;
        }
    
        ~ThreadPool()
        {
          pthread_mutex_destroy(&lock);
          pthread_cond_destroy(&cond);
        }
    };
    
    
    #include "ThreadPool.hpp"
    
    int main()
    {
      ThreadPool *tp = new ThreadPool();
      tp->ThreadPoolInit();
      
      //server一直构造任务
      while(true)
      {
        int x = rand()%10+1;
        Task t(x);
        tp->Put(t);
        sleep(1);
      }
    
      return 0;
    }
    

    在这里插入图片描述
    线程池存在的价值

    1. 有任务,立马有线程进行服务,省掉了线程创建的时间。
    2. 有效防止server中线程过多,导致系统过载的问题。
    3. 可以避免在峰值压力下,系统资源耗尽的风险;并且可以统一对线程池中的线程进行管理,调度监控。

    线程池vs进程池:

    1. 线程池占用资源更少,但鲁棒性不强。
    2. 进程池占用资源更多,但鲁棒性强。

    单例模式

    定义:确保一个类最多只有一个实例,并提供一个全局访问点

    单例模式可以分为两种:预加载和延时加载

    饿汉模式

    预加载,再进一步解释就是还没有使用该单例对象,但是,该单例对象就已经被加载到内存了。

    template<class T>
    class singlen
    {
    public:
        //禁止构造,禁止拷贝构造,禁止拷贝
        static T* GetInstance()
        {
            return &data_;
        }
    private:
        static T data;
    };
    
    

    优点:程序运行速度很快;缺点:程序初始化的时候就耗时比较长。

    懒汉模式–延时加载

    资源在使用的时候才进行实例化,单例列的对象在使用的时候才进行实例化。

    class singten
    {
    public:
    	static singten* GetInstance();
    private:
        signlen();
        volatile static singten* p;
    };
    static singten* GetInstance()
    {
        if(p==NULL)
        {
            pthread_mutex_lock(&locK_);
            if(p==NULL)
            {
                p=new singten();
            }
            pthread_mutex_unlock(&lock_);
        }
        return p;
    }
    
    
    1. 互斥锁保证线程安全
    2. 双重if判空,降低锁竞争的概率
    3. volatile关键字防止过度优化
    展开全文
  • 个人倾向享元模式。 https://zhidao.baidu.com/question/181310353265055884.html代理模式,命令模式,享元模式,不确定。 评论
  • maven-text-demo 练习使用 反射- 注解 -过滤器-线程池--设计模式
  • 设计模式是一套被反复使用的、多数人知晓、经过分类编目的优秀代码设计经验的总结。特定环境下特定问题的处理方法。 •重用设计和代码 重用设计比重用代码更有意义,自动带来代码重用 •提高扩展性 大量使用面向...
  • 1.线程组的概述和使用 Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。  (1)默认情况下,所有线程都属于线程组  public final ThreadGroup ...
  • 一堆线程进行任务处理,主要针对大量任务需要处理的场景,使用多执行流可以提高处理效率 如果一个任务到来就创建一个线程来处理这有很大缺点: 成本:总耗时=线程创建时间+任务处理时间+线程销毁时间,如果任务处理时间...
  • Javaday24 线程池 设计模式 一 线程间的等待唤醒机制 object类中 void wait()在其他线程调用此对象那个的notify()方法或者notifyAll()方法前,导致当前线程等待。 void wait (long timeout) 在其他线程调用此...
  • 工厂模式 主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。    工厂方法模式: 一个抽象产品类,可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个...
  • 线程池设计

    千次阅读 2022-03-07 21:34:42
    线程池核心设计与实现 2.1 总体设计 Java中的线程池核心实现类是ThreadPoolExecutor ThreadPoolExecutor实现的顶层接口是Executor,顶层接口Executor提供了一种思想:将任务提交和任务执行进行解耦。用户无需关注...
  • 享元模式的适用场景是什么? 围棋设计。 为什么要用享元模式? 节省内存开销。
  • 下面小编就为大家带来一篇java 可重启线程及线程池类的设计(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • import javax.annotation.PreDestroy; import java.util.concurrent.*;... * 自定义线程池 */ public class ThreadPool { /** * 自定义线程池 * @return */ private final int CORE_POOL_SIZE = 5; ...
  • Thread Pool(线程池
  • 也看过很多高级教程,觉得自己还是比较热衷于js的设计模式。这一次重温一下《JavaScript设计模式与开发实践》,开篇为单例模式。 /** * pre 单例模式 * 定义:保证一个类仅有一个实例,并提供一个访问它的全局...
  • 因为在一个程序中往往都只会使用一个线程池,所以为了代码更加的完善,我们可以使用单例模式来创建线程池,单例模式是一种设计模式,特点是它私有化了构造方法,内部创建了一个需要返回的对象,比如我们创建线程池...
  • 前言 Builder 设计模式也叫做 构建者模式或者建造者模式,名字只是一种叫法,当聊起三种名称的时候知道是怎么回事...这里必须提一句:设计模式重要的是思想,一种设计模式可能不止一种实现方式 Builder 模式文章大纲.
  • ①并发型模式(半同步/半异步模式): 并发编程的目的是让程序“同时”执行多个任务。 并发模式是指I/O(输入/输出)处理单元和多个逻辑单元之间协调完成任务的方法,在服务器上主要有两种并发编程模式:半同步/半...
  • 单例模式创建线程池使用

    万次阅读 2017-01-15 15:14:13
    因为在一个程序中往往都只会使用一个线程池,所以为了代码更加的完善,我们可以使用单例模式来创建线程池,单例模式是一种设计模式,特点是它私有化了构造方法,内部创建了一个需要返回的对象,比如我们创建线程池...
  • 前面在写到多线程的文章的时候,一直想写一篇关于线程池等一系列的文章,做一下记录,本篇博客记录一下设计模式中享元模式的设计思想,以及使用享元模式的实现案例——线程池,以及线程池的简化版——任务(task) ...
  • ** java相关jvm,线程池设计模式学习笔记-XMind **
  • java常用23中设计模式

    2018-10-25 10:23:54
    总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元...
  • 线程池 线程安全的单例模式 饿汉方式 懒汉方式

    多人点赞 热门讨论 2021-04-27 19:29:27
    线程池: 第一个线程安全任务队列+提前创建好最大数据上限的工作线程; 针对大量数据请求处理的场景; 好处: 1.避免大量线程频繁创建与销毁带来的时间成本; 2.任务节点以及线程有上限,避免资源耗尽的风险; 核心...
  • Java常见设计模式总结

    万次阅读 多人点赞 2021-09-18 17:18:54
    设计模式是一套经过反复使用的代码设计经验,目的是为了重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式于己于人于系统都是多赢的,它使得代码编写真正工程化,它是软件工程的基石,如同大厦的一块块...
  • 这种分工模式如果用 Java Thread 实现,频繁地创建、销毁线程非常影响性能,同时无限制地创建线程还可能导致 OOM,所以在 Java 领域使用场景就受限了。      要想有效避免线程的频繁创建、销毁以及 OOM 问题,就...
  • JS的五大设计模式

    2021-01-08 18:15:58
    比如说线程池、全局缓存、浏览器中的window对象,我 们在前端也经常会使用到单例,当我们点击登录按钮的时候,我们会出现一个登录的副创,这个浮窗是唯 一的,无论我们点击多少次,这个浮窗仅仅会被创建一次,那么这...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 107,900
精华内容 43,160
关键字:

线程池使用的设计模式