精华内容
下载资源
问答
  • 在 Java 语言中,从 Java 5 开始, Java 提供了自己的线程池 ThreadPoolExec 引言  在涉及多线程并发操作时,如何管理多线程对共享数据的访问以及防止线程间的死锁问题是个很重要的话题。在 Java 语言中,从 ...

    引言 在涉及多线程并发操作时,如何管理多线程对共享数据的访问以及防止线程间的死锁问题是个很重要的话题。在 Java 语言中,从 Java 5 开始, Java 提供了自己的线程池 ThreadPoolExec

    引言

        在涉及多线程并发操作时,如何管理多线程对共享数据的访问以及防止线程间的死锁问题是个很重要的话题。在 Java 语言中,从 Java 5 开始, Java 提供了自己的线程池 ThreadPoolExecutor 类;在 iPhone 中则提供了 NSOperationQueue 类进行多线程的管理和调度。

    什么是线程池?

    线程池到底是怎么一回事呢?其实线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的典型的执行流程如下:

    首先,启动若干数量的线程,并让这些线程处于睡眠状态

    其次,当客户端有新的请求时,线程池会唤醒某一个睡眠线程,让它来处理客户端的请求

    最后,当请求处理完毕,线程又处于睡眠状态

    Java 线程池

        线程池可以由程序员自己来实现,但是从 Java 5 开始, Java 语言自带了线程池的类 ThreadPoolExecutor ,这个类提供了典型的线程池管理的接口,来研究 ThreadPoolExecutor 类的实现无疑更有借鉴意义。

        ThreadPoolExcutor 类常用的构造方式为

    ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler)

    参数 corePoolSize 为线程池维护线程的最少数量
    参数 maximumPoolSize 为线程池维护线程的最大数量
    参数 keepAliveTime 为线程池维护线程所允许的空闲时间
    参数 unit 为线程池维护线程所允许的空闲时间的单位
    参数 workQueue 为线程池所使用的缓冲队列
    参数 handler 为线程池对拒绝任务的处理句柄

        一个任务可以通过 excute(Runnable) 方法被添加到线程池,任务就是一个实现了 Runnable 接口的对象,而线程池通过 Runnable 类型对象的 run() 方法来执行任务。

        典型的用法如下:

        首先,构造一个线程池

    ThreadPoolExecutor threadPool =
    new ThreadPoolExecutor(2,4,3,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(3),new ThreadPoolExecutor.DiscardOldestPolicy());
    for(int i = 1;i <= 5;i++)
    {
    
         try
    {
         String task = “task@”+i;
         System.out.println(“put”+task);
         threadPool.execute(new ThreadPoolTask());
    }
    }
    catch(Exception e)
    {
         e.printStackTrace();
    }

        而线程池所要执行的任务对象需要实现 Runnable 接口,线程池执行任务对象时调用任务对象的 run() 方法,它的实现代码如下:

    public class ThreadPoolTask implements Runnable{
    ThreadPoolTask(){}
    public void run(){
         System.out.println(“start execute”);
    }
    }

    iPhone 操作队列

        iPhone 本身也支持多线程开发,同样, NSThread 类提供对多线程开发的支持时也面临多线程的共享数据管理和死锁问题,于是 iPhone 也提供了类似于 Java 线程池的解决方案:任务队列 NSOperationQueue 类。

        和 Java 语言的 Runnable 接口一样, iPhone 提供了 NSOperation 接口进行任务对象的封装,而通过将任务对象加入到 NSOperationQueue 队列, NSOperationQueue 队列会分配线程进行任务对象的执行,任务对象的执行通过 - (void)main 方法,下面是典型的任务对象和任务队列的实现:

    @interface ThreadPoolTask:NSOperation
    {
    }
    @end
    
    @implementation ThreadPoolTask
    - (void)main
    {
      NSLog(@”start execute”);
    }
    @end

        和 Java 语言中一样,构造一个多线程池并添加任务对象到线程池中,线程池会调用任务对象的 - (void)main 方法执行任务, iPhone 中典型的任务队列的实现如下:

    NSOperationQueue* threadPool = [[NSOperation alloc] init];
    [threadPool setMaxConcurrentOperationCount:4];
    for(int i = 1;i <= 5;i++)
    {        
    NSString* task = [NSString stringWithFormat:@”task %d”,i];
    NSLog(@“put %@”,task);
    [threadPool add:([[ThreadPoolTask alloc] init])];
    }

        可以看到, iPhone 通过 NSOperationQueue 提供了一套类似于线程池的机制,通过它可以更加方便的进行多线程的并发操作,从而使得程序员从繁杂的多线程共享数据管理和死锁问题中解脱出来。

     

    转自 http://blog.csdn.NET/dongfengsun/archive/2011/01/12/6130683.aspx

    展开全文
  • 线程池原理

    2012-05-27 16:29:38
    本文通过了解线程池的简单源代码,了解其工作原理。 1)线程池需要初始化时候,指定工作线程数; 2)每次加入工作任务,都需要调用 线程池函数 pool.Call(其中,各个线程可以调用不同的函数) // ...
     
    

        本文通过了解线程池的简单源代码,了解其工作原理。

    1)线程池需要初始化时候,指定工作线程数;

    2)每次加入工作任务,都需要调用 线程池函数    pool.Call(其中,各个线程可以调用不同的函数)



    //   threadPool.h


    #ifndef _ThreadPool_H_
    #define _ThreadPool_H_
    #pragma warning(disable: 4530)
    #pragma warning(disable: 4786)
    #include <cassert>
    #include <vector>
    #include <queue>
    #include <windows.h>


    using namespace std;


    class ThreadJob  //工作基类
    {
    public:
        //供线程池调用的纯虚函数
        virtual void DoJob(void *pPara) = 0;
    };








    class ThreadPool
    {
    public:
        //dwNum 线程池规模
        ThreadPool(DWORD dwNum = 4) : _lThreadNum(0), _lRunningNum(0) 
        {
            InitializeCriticalSection(&_csThreadVector);
            InitializeCriticalSection(&_csWorkQueue);
            _EventComplete = CreateEvent(0, false, false, NULL);
            _EventEnd = CreateEvent(0, true, false, NULL);
            _SemaphoreCall = CreateSemaphore(0, 0,  0x7FFFFFFF, NULL);
            _SemaphoreDel =  CreateSemaphore(0, 0,  0x7FFFFFFF, NULL);
            assert(_SemaphoreCall != INVALID_HANDLE_VALUE);
            assert(_EventComplete != INVALID_HANDLE_VALUE);
            assert(_EventEnd != INVALID_HANDLE_VALUE);
            assert(_SemaphoreDel != INVALID_HANDLE_VALUE);
            AdjustSize(dwNum <= 0 ? 4 : dwNum);
        }
        ~ThreadPool()
        {
            DeleteCriticalSection(&_csWorkQueue);
            CloseHandle(_EventEnd);
            CloseHandle(_EventComplete);
            CloseHandle(_SemaphoreCall);
            CloseHandle(_SemaphoreDel);


            vector<ThreadItem*>::iterator iter;
            for(iter = _ThreadVector.begin(); iter != _ThreadVector.end(); iter++)
            {
                if(*iter)
                    delete *iter;
            }
            DeleteCriticalSection(&_csThreadVector);
        }
        //调整线程池规模
        int AdjustSize(int iNum)
        {
            if(iNum > 0)
            {
                ThreadItem *pNew;
                EnterCriticalSection(&_csThreadVector);
                for(int _i=0; _i<iNum; _i++)
                {
                    _ThreadVector.push_back(pNew = new ThreadItem(this)); 
                    assert(pNew);
                    pNew->_Handle = CreateThread(NULL, 0, DefaultJobProc, pNew, 0, NULL);
                    // set priority
                    SetThreadPriority(pNew->_Handle, THREAD_PRIORITY_BELOW_NORMAL);
                    assert(pNew->_Handle);
                }
                LeaveCriticalSection(&_csThreadVector);
            }
            else
            {
                iNum *= -1;
                ReleaseSemaphore(_SemaphoreDel,  iNum > _lThreadNum ? _lThreadNum : iNum, NULL);
            }
            return (int)_lThreadNum;
        }
        
        //增加工作任务
        void Call(void (*pFunc)(void  *), void *pPara = NULL)
        {
            assert(pFunc);
            EnterCriticalSection(&_csWorkQueue);
            _WorkQueue.push(new JobItem(pFunc, pPara));
            LeaveCriticalSection(&_csWorkQueue);
            ReleaseSemaphore(_SemaphoreCall, 1, NULL);
        }
        //调用线程池用户对象结构
        inline void Call(ThreadJob * p, void *pPara = NULL)
        {
            //增加工作任务
            Call(CallProc, new CallProcPara(p, pPara));
        }
        //结束线程池, 并同步等待
        bool EndAndWait(DWORD dwWaitTime = INFINITE)
        {
            SetEvent(_EventEnd);
            return WaitForSingleObject(_EventComplete, dwWaitTime) == WAIT_OBJECT_0;
        }
        //结束线程池
        inline void End()
        {
            SetEvent(_EventEnd);
        }
        inline DWORD Size()
        {
            return (DWORD)_lThreadNum;
        }
        inline DWORD GetRunningSize()
        {
            return (DWORD)_lRunningNum;
        }
        bool IsRunning()
        {
            return _lRunningNum > 0;
        }
    protected:
        //工作线程
        static DWORD WINAPI DefaultJobProc(LPVOID lpParameter = NULL)
        {
            ThreadItem *pThread = static_cast<ThreadItem*>(lpParameter);
            assert(pThread);
            ThreadPool *pThreadPoolObj = pThread->_pThis;
            assert(pThreadPoolObj);
            InterlockedIncrement(&pThreadPoolObj->_lThreadNum);
            HANDLE hWaitHandle[3];
            hWaitHandle[0] = pThreadPoolObj->_SemaphoreCall;
            hWaitHandle[1] = pThreadPoolObj->_SemaphoreDel;
            hWaitHandle[2] = pThreadPoolObj->_EventEnd;
            JobItem *pJob;
            bool fHasJob;


            for(;;)
            {
                DWORD wr = WaitForMultipleObjects(3, hWaitHandle, false, INFINITE);
                //响应删除线程信号
                if(wr == WAIT_OBJECT_0 + 1)  
                    break;


                //从队列里取得用户作业
                EnterCriticalSection(&pThreadPoolObj->_csWorkQueue);
                if(fHasJob = !pThreadPoolObj->_WorkQueue.empty())
                {
                    pJob = pThreadPoolObj->_WorkQueue.front();
                    pThreadPoolObj->_WorkQueue.pop();
                    assert(pJob);
                }
                LeaveCriticalSection(&pThreadPoolObj->_csWorkQueue);


                //受到结束线程信号 确定是否结束线程(结束线程信号 && 是否还有工作)
                if(wr == WAIT_OBJECT_0 + 2 && !fHasJob)  
                    break;
                if(fHasJob && pJob)
                {
                    InterlockedIncrement(&pThreadPoolObj->_lRunningNum);
                    pThread->_dwLastBeginTime = GetTickCount();
                    pThread->_dwCount++;
                    pThread->_fIsRunning = true;
                    pJob->_pFunc(pJob->_pPara); //运行用户作业
                    delete pJob; 
                    pThread->_fIsRunning = false;
                    InterlockedDecrement(&pThreadPoolObj->_lRunningNum);
                }
            }
            //删除自身结构
            EnterCriticalSection(&pThreadPoolObj->_csThreadVector);
            pThreadPoolObj->_ThreadVector.erase( \
                 find(pThreadPoolObj->_ThreadVector.begin(), pThreadPoolObj->_ThreadVector.end(), pThread));
            LeaveCriticalSection(&pThreadPoolObj->_csThreadVector);
            delete pThread;
            InterlockedDecrement(&pThreadPoolObj->_lThreadNum);
            if(!pThreadPoolObj->_lThreadNum)  //所有线程结束
                SetEvent(pThreadPoolObj->_EventComplete);
            return 0;
        }
        //调用用户对象虚函数
        static void CallProc(void *pPara) 
        {
            CallProcPara *cp = static_cast<CallProcPara *>(pPara);
            assert(cp);
            if(cp)
            {
                cp->_pObj->DoJob(cp->_pPara);
                delete cp;
            }
        }
        //用户对象结构
        struct CallProcPara  
        {
            ThreadJob* _pObj;//用户对象 
            void *_pPara;//用户参数
            CallProcPara(ThreadJob* p, void *pPara) : _pObj(p), _pPara(pPara) { };
        };
        //用户函数结构
        struct JobItem 
        {
            void (*_pFunc)(void  *);//函数
            void *_pPara; //参数
            JobItem(void (*pFunc)(void  *) = NULL, void *pPara = NULL) : _pFunc(pFunc), _pPara(pPara) { };
        };
        //线程池中的线程结构
        struct ThreadItem
        {
            HANDLE _Handle; //线程句柄
            ThreadPool *_pThis;  //线程池的指针
            DWORD _dwLastBeginTime; //最后一次运行开始时间
            DWORD _dwCount; //运行次数
            bool _fIsRunning;
            ThreadItem(ThreadPool *pthis) : _pThis(pthis), _Handle(NULL), _dwLastBeginTime(0),
                                        _dwCount(0), _fIsRunning(false) { };
            ~ThreadItem()
            {
                if(_Handle)
                {
                    CloseHandle(_Handle);
                    _Handle = NULL;
                }
            }
        };


        std::queue<JobItem *> _WorkQueue;            //工作队列
        std::vector<ThreadItem *>  _ThreadVector;   //线程数据
        CRITICAL_SECTION _csThreadVector, _csWorkQueue; //线程数据临界, 工作队列临界
                
                //结束通知, 完成事件, 工作信号, 删除线程信号
        HANDLE _EventEnd, _EventComplete, _SemaphoreCall, _SemaphoreDel;
        long _lThreadNum, _lRunningNum; //线程数, 运行的线程数
    };

    #endif //_ThreadPool_H_



    //main.cpp

    #include "threadPool.h"
    #include <iostream>
    #include <fstream>

    using namespace std;


    CRITICAL_SECTION _csGuardCount; //保护全局变量

    static int g_iCount = 0;


    void Show( void *parm)
    {
        EnterCriticalSection(&_csGuardCount);
        int i = *(int *) parm;
        cout << "threadId:" << i <<endl;   //标记为A 

        char szName[64] = {0};
        sprintf(szName, "./file%d.txt", g_iCount);
        fstream outFile;
        outFile.open(szName, ios::out); 
        if(outFile.is_open())
        {
            cout << "open  OK"  << endl;  
            g_iCount ++;
            outFile <<"g_iCount:" << g_iCount-1<<endl;
        }
        else
        {
            cout << "open error:" <<   GetLastError() << endl; 
        }


        LeaveCriticalSection(&_csGuardCount);


     
        Sleep(10 * 1000);
        cout << "end"  << endl;  
    }   




    class MyJob:public ThreadJob
    {
    public:
        virtual void DoJob(void *pPara)
        {


            if (pPara == NULL)
            {
                Show("pPara == NULL");
            }
            else
            { 
                Show(pPara);
            }
        }
    };


    int main(int argc, char* argv[])
    {
        ThreadPool pool(2);


        InitializeCriticalSection(&_csGuardCount);




        MyJob job;
        
        int iThteadId = 1;
        pool.Call(&job, &iThteadId);
        iThteadId = 2;
        pool.Call(&job, &iThteadId);
        iThteadId = 3;
        pool.Call(&job, &iThteadId);
        iThteadId = 4;
        pool.Call(&job, &iThteadId);
        iThteadId = 5;
        pool.Call(&job, &iThteadId);
        iThteadId = 6;
        pool.Call(&job, &iThteadId);
     
        getchar();
        pool.AdjustSize(100);    //标记为B
         
        system("pause");
        DeleteCriticalSection(&_csGuardCount);


        return 0;
    }




    程序中,发现线程是同时执行的,因此标记处A可能一样;另外,考虑到起始是创建了2个线程,如果要运行多个任务,发现很慢,但是如果执行标记处B,则可以加速运行。原因是:回车后,对线程池进行了调整,又参加了100个线程。(可以看任务管理器 ,需要对任务区管理器:查看-----选择利----线程数)。


    本程序,只是手动对其进行线程数调整,之后,可以智能化,当任务超过初始值的线程数很多时候,可以进行适当调整加大。
    (当然,就是因为这样,才体现线程池的优越性,不需要因为任务量多,而需要创建线程也多)。
    展开全文
  • Java线程池原理详解

    2016-11-17 11:26:37
    http://www.toutiao.com/i6350844998358925825/?tt_from=mobile_qq&utm_campaign=client_share&app=news_article&utm_source=mobile_qq&iid=6176041275&utm_medium=toutiao_ios
    展开全文
  • 线程池实现原理

    2019-03-14 00:24:24
    jdk1.5引入Executor线程池框架,通过它把任务的提交和执行进行解耦,只需要定义好任务,然后提交给线程池,而不用关心该任务是如何执行、被哪个线程执行,以及什么时候执行。 初始化线程池(4种) 简介: Java...

    jdk1.5引入Executor线程池框架,通过它把任务的提交和执行进行解耦,只需要定义好任务,然后提交给线程池,而不用关心该任务是如何执行、被哪个线程执行,以及什么时候执行。

    初始化线程池(4种)

    简介:

    Java线程池的工厂类:Executors类,

    初始化4种类型的线程池:

    newFixedThreadPool()
    说明:初始化一个指定线程数的线程池,其中corePoolSize == maxiPoolSize,使用LinkedBlockingQuene作为阻塞队列
    特点:即使当线程池没有可执行任务时,也不会释放线程。
    newCachedThreadPool()
    说明:初始化一个可以缓存线程的线程池,默认缓存60s,线程池的线程数可达到Integer.MAX_VALUE,即2147483647,内部使用SynchronousQueue作为阻塞队列;
    特点:在没有任务执行时,当线程的空闲时间超过keepAliveTime,会自动释放线程资源;当提交新任务时,如果没有空闲线程,则创建新线程执行任务,会导致一定的系统开销;
    因此,使用时要注意控制并发的任务数,防止因创建大量的线程导致而降低性能。
    newSingleThreadExecutor()
    说明:初始化只有一个线程的线程池,内部使用LinkedBlockingQueue作为阻塞队列。
    特点:如果该线程异常结束,会重新创建一个新的线程继续执行任务,唯一的线程可以保证所提交任务的顺序执行
    newScheduledThreadPool()
    特定:初始化的线程池可以在指定的时间内周期性的执行所提交的任务,在实际的业务场景中可以使用该线程池定期的同步数据。

    总结:除了newScheduledThreadPool的内部实现特殊一点之外,其它线程池内部都是基于ThreadPoolExecutor类(Executor的子类)实现的。

    ThreadPoolExecutor内部具体实现:

    ThreadPoolExecutor类构造器语法形式:

    ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveTime,timeUnit,workQueue,threadFactory,handle);   

    方法参数:
       corePoolSize:核心线程数
       maxPoolSize:最大线程数
         keepAliveTime:线程存活时间(在corePore<*<maxPoolSize情况下有用)
         timeUnit:存活时间的时间单位
         workQueue:阻塞队列(用来保存等待被执行的任务)

    注:关于workQueue参数的取值,JDK提供了4种阻塞队列类型供选择:
            ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO排序任务;
            inkedBlockingQuene:基于链表结构的阻塞队列,按FIFO排序任务,吞吐量通常要高于  

                SynchronousQuene:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于ArrayBlockingQuene;

            PriorityBlockingQuene:具有优先级的无界阻塞队列

         threadFactory:线程工厂,主要用来创建线程;

         handler:表示当拒绝处理任务时的策略,有以下四种取值

     注: 当线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务,线程池提供了4种策略:

        ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

        ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。

        ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

        ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

        当然也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,如记录日志或持久化存储不能处理的任务。


     线程池的状态(5种)

    其中AtomicInteger变量ctl的功能非常强大:利用低29位表示线程池中线程数,通过高3位表示线程池的运行状态:
    1、RUNNING:-1 << COUNT_BITS,即高3位为111,该状态的线程池会接收新任务,并处理阻塞队列中的任务;
    2、SHUTDOWN: 0 << COUNT_BITS,即高3位为000,该状态的线程池不会接收新任务,但会处理阻塞队列中的任务;
    3、STOP : 1 << COUNT_BITS,即高3位为001,该状态的线程不会接收新任务,也不会处理阻塞队列中的任务,而且会中断正在运行的任务;
    4、TIDYING : 2 << COUNT_BITS,即高3位为010,该状态表示线程池对线程进行整理优化;
    5、TERMINATED: 3 << COUNT_BITS,即高3位为011,该状态表示线程池停止工作;


     向线程池提交任务(2种)

    有两种方式:

          Executor.execute(Runnable command);

          ExecutorService.submit(Callable<T> task);

    execute()内部实现

    1.首次通过workCountof()获知当前线程池中的线程数,

      如果小于corePoolSize, 就通过addWorker()创建线程并执行该任务;

     否则,将该任务放入阻塞队列;

    2. 如果能成功将任务放入阻塞队列中,  

    如果当前线程池是非RUNNING状态,则将该任务从阻塞队列中移除,然后执行reject()处理该任务;

    如果当前线程池处于RUNNING状态,则需要再次检查线程池(因为可能在上次检查后,有线程资源被释放),是否有空闲的线程;如果有则执行该任务;

    3、如果不能将任务放入阻塞队列中,说明阻塞队列已满;那么将通过addWoker()尝试创建一个新的线程去执行这个任务;如果addWoker()执行失败,说明线程池中线程数达到maxPoolSize,则执行reject()处理任务;

     sumbit()内部实现

    会将提交的Callable任务会被封装成了一个FutureTask对象

    FutureTask类实现了Runnable接口,这样就可以通过Executor.execute()提交FutureTask到线程池中等待被执行,最终执行的是FutureTask的run方法; 

    比较:

     两个方法都可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中, 而submit()方法可以返回持有计算结果的Future对象,它定义在ExecutorService接口中,它扩展了Executor接口,其它线程池类像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有这些方法。 


    线程池的关闭(2种)

      ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow(),其中:

        shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务

        shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务


     线程池容量的动态调整

      ThreadPoolExecutor提供了动态调整线程池容量大小的方法:setCorePoolSize()和setMaximumPoolSize(),

     

     

    总结:

    线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize;如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;如果阻塞队列满了,那就创建新的线程执行当前任务;直到线程池中的线程数达到maxPoolSize,这时再有任务来,只能执行reject()处理该任务;

    注:如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。

    展开全文
  • 线程池原理及实现

    2018-07-12 17:40:34
    1、线程池简介: 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。 假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中...
  • 引言 在涉及多线程并发操作时,如何管理多线程对共享数据的访问以及防止线程间的死锁问题是个很重要的话题。在 Java 语言中,从Java 5 开始, Java 提供了自己的线程池 ...其实线程池原理
  • 多线程2.1 多线程的意义2.2 多线程的原理2.3 多线程技术方案2.3 多线程生命周期2.4 线程池原理 1. 线程和进程 1.1 线程和进程的定义 线程 线程是进程的基本执行单元,一个进程的所有任务都在线程中执行。 进程要...
  • iOS 底层原理 文章汇总 本文的目的在于了解进程、线程、多线程、线程池等的基本概念及原理 线程 和 进程 线程和进程的定义 线程 线程时进程的基本执行单元,一个进程的所有任务都在线程中执行 进程要想执行任务,...
  • 我们知道 dyld 的加载过程,即在 App 启动启动执行 main 函数之前,dylb 主要作了环境变量配置、共享缓存、主程序的初始化、插入动态库、链接主程序、链接动态库、弱...:iOS之深入解析App启动dyld加载流程的底层原理...
  • iOS多线程——概念与原理

    千次阅读 2020-11-05 16:41:52
    iOS的多线程,很多人用起来都很熟悉,本文将简单介绍一下其概念和原理,以及多线程与runloop的关系。
  • iOS 底层原理 文章汇总 本文的主要目的是理解dyld与objc是如何关联的 在上一篇文章iOS-底层原理 15:dyld加载流程 中,我们梳理了dyld的加载流程,下面来详细介绍下dyld和objc的关联 _objc_init 源码解析 首先,来...
  • 它是一个在线程池模式的基础上执行的并发任务。 GCD的优点 GCD支持多核并行计算 GCD自动管理线程的生命周期(线程的创建、调起、等待、销毁) 使用者只需告知GCD执行任务 任务与队列 任务 任务即执行操作,就是...
  • iOS 多线程详解

    2018-05-15 17:56:46
    iOS 多线程详解 Slogan : 可能是最通俗易懂的 iOS多线程 详细解析文章 1. 基础概念 1.1 进程 进程是计算机中已运行程序的实体,是线程的容器维基百科-进程。每个进程之间是相互独立的,每个进程均运行在器...
  • iOS总结

    千次阅读 2016-08-26 22:02:14
    iOS总结
  • iOS 理解

    2016-07-17 13:08:22
    iOS 理解
  • iOS之深入解析“锁”的底层原理

    万次阅读 2021-05-11 01:34:18
    自从 OSSpinLock 出现安全问题,在 iOS10 之后就被 Apple 废弃。自旋锁之所以不安全,是因为获取锁后,线程会一直处于忙等待,造成了任务的优先级反转; 其中的忙等待机制可能会造成高优先级任务一直 running 等待,...
  • 哈哈,言归正传,安闲之余,看操作系统原理一书,里面有一章节讲解的是死锁,很多人认为,死锁是很高端的操作系统层面的问题,离我们很远,一般不会遇上。其实这种想法是非常错误的,作为一名iOS开发,在iOS中,下面...
  • 提示:iOS的开发者,需要了解三种多线程技术的基本使用,因为在实际开发中会根据实际情况选择不同的多线程技术 2 GCD - Grand Central Dispatch 2.1 GCD基本思想 GCD的基本思想是就将操作s放在队列s中...
  • iOS面试题

    2016-03-10 16:43:50
    iOSios面试题ios面试题和答案ios面试题及答案 史上最全的iOS面试题及答案iOS面试小贴士———————————————回答好下面的足够了————————————-多线程、特别是NSOperation 和 GCD 的内部原理。...
  • iOS GCD

    2015-10-12 21:17:19
    一、简介: ...它是一个在线程池模式的基础上执行的并行任务。在Mac OS X 10.6雪豹中首次推出,也可在IOS 4及以上版本使用。 GCD是一个替代诸如NSThread等技术的很高效和强大的技术。GCD完全可以处
  • iOS中多线程原理与runloop介绍 iPhone中的线程应用并不是无节制的,官方给出的资料显示iPhone OS下的主线程的堆栈大小是1M,第二个线程开始都是512KB。并且该值不能通过编译器开关或线程API函数来更改。只有主线程...
  • 本文的目的在于了解进程、线程、多线程、线程池等的基本概念及原理 线程 和 进程 线程和进程的定义 线程 线程时进程的基本执行单元,一个进程的所有任务都在线程中执行 进程要想执行任务,必须的有线程,进程...
  • 线程池和饱和策略 饱和策略 AbortPolicy 直接抛出RejectedExecutionExeception异常来阻止系统正常运行 CallerRunsPolicy 将任务回退到调用者 DisOldestPolicy 丢掉等待最久的任务‘ DisCardPolicy 直接丢弃任务 6....
  • iOS开发--- iOS编程浅析

    2015-04-08 10:22:54
    IOS系统委托机制与Core location预处理MapKit框架XIB文件所有者UIViewUIScrollView隐藏状态条UITabBarControllerUIWindow载入XIB文件UIVIewControllerUITableView UITableViewController UITableViewCell对象 ...
  • iOS GCD 基础

    2017-09-30 16:12:30
    iOS GCD 基础介绍
  • iOS

    2013-05-17 10:45:08
    面试能力要求:精通iphone的UI开发,能熟练操作复杂表视图,熟练使用图层技术, 可以自定义UI控件,使用类别扩展系统控件功能; 擅长通讯技术,熟悉各种通信协议,精通xml, json, 二进制或其他形式的自定义解析,...
  • iOS开发进阶

    千次阅读 2015-07-01 21:21:50
    iOS多线程编程之NSThread的使用 1、简介: 1.1 iOS有三种多线程编程的技术,分别是: 1.、NSThread  2、Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的使用) 3、GCD 全称:Grand ...
  • IOS面试题汇总

    千次阅读 2014-02-21 20:37:28
    
但是后来看到一票关于这操作队列话题的文章,其中有一句提到
“因为两个操作提交的时间间隔很近,线程池中的线程,谁先启动是不定的。”
瞬间觉得这个queue名字有点忽悠人了,还不如pool~
综合一点,我们知道他...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,141
精华内容 2,456
关键字:

线程池原理ios