精华内容
下载资源
问答
  • Object中的wait()、notify()让线程等待和唤醒 Object.wait()、Object.notify()方法必须再synchronized修饰的代码块中才能正常使用,否则会报异常(语法不会显示有错误) 如下如果注释synchronized (obj)会报java.lang....

    Object中的wait()notify()让线程等待和唤醒

    Object.wait()Object.notify()方法必须再synchronized修饰的代码块中才能正常使用,否则会报异常(语法不会显示有错误)

    如下如果注释synchronized (obj)会报java.lang.IllegalMonitorStateException: current thread is not owner

    正常使用必须在synchronized中使用!
    public static void main(String[] args) {
        Object obj = new Object();
        new Thread(() -> {
           // synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + "\t======== 进入");
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "\t======== 被唤醒");
           // }
        }, "A").start();
    
        new Thread(() -> {
            //synchronized (obj) {
                obj.notify();
                System.out.println(Thread.currentThread().getName()+"\t============ 通知");
            //}
        }, "B").start();
    }
    

    Condition中的await()signal()让线程等待和唤醒

    Condition需要在ReentrantLock下使用,也就是需要上锁和释放锁,否则也会报java.lang.IllegalMonitorStateException

    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition condition=lock.newCondition();
    
        new Thread(() -> {
    //            lock.lock();
                System.out.println(Thread.currentThread().getName() + "\t======== 进入");
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
    //                    lock.unlock();
                }
                System.out.println(Thread.currentThread().getName() + "\t======== 被唤醒");
        }, "A").start();
    
        new Thread(() -> {
    //            lock.lock();
            try {
                condition.signal();
                System.out.println(Thread.currentThread().getName()+"\t============ 通知");
            } finally {
    //                lock.unlock();
            }
        }, "B").start();
    }
    

    LockSupport中的park()unpark()

    LockSupport调用unpark方法最多只发放一个许可证,调用park则需要消耗一个许可证。
    换而言之

    如下的逻辑虽然调用了两次unpark,但LockSupport只发放一个许可证

    LockSupport.unpark(t1)//需要传入参数线程t1
    LockSupport.unpark(t1)//需要传入参数线程t1
    LockSupport.park()
    LockSupport.park()// 线程会阻塞
    

    另外LockSupport.park()和LockSupport.unpark()不影响正常使用阻塞

    LockSupport.unpark(t1)//需要传入参数线程t1
    LockSupport.park()
    // 上面的顺序和下面的调用顺序,两者的作用相同
    LockSupport.park()
    LockSupport.unpark(t1)//需要传入参数线程t1
    

    总而概之,LockSupport是一个线程阻塞的工具类,里面的所有方法都是静态的

    相关文章:

    1、LockSupport源码的简化

    2、LockSupport中文文档

    展开全文
  • pthread_cond_timedwait()函数pthread_cond_wait()函数,其实2个函数都差不多,我主要是要用pthread_cond_timedwait()函数。 pthread_cond_timedwait()函数有三个入口参数: (1)pthread_cond_t __cond:条件变量...

    pthread_cond_timedwait()函数和pthread_cond_wait()函数,其实2个函数都差不多,我主要是要用pthread_cond_timedwait()函数。

    pthread_cond_timedwait()函数有三个入口参数:

    (1)pthread_cond_t __cond:条件变量(触发条件)

    (2)pthread_mutex_t __mutex: 互斥锁

    (3)struct timespec __abstime: 等待时间(其值为系统时间 + 等待时间)

    当在指定时间内有信号传过来时,pthread_cond_timedwait()返回0,否则返回一个非0数(我没有找到返回值的定义);

    在使用pthread_cond_timedwait()函数时,必须有三步:

    1:加互斥锁:pthread_mutex_lock(&__mutex)

    2:等待:pthread_cond_timedwait(&__cond, &__mutex, &__abstime)   //解锁->等待->加锁

    3:解互斥锁:pthread_mutex_unlock(&__mutex)

    发送信号量时,也要有三步:

    1:加互斥锁:pthread_mutex_lock(&__mutex)

    2:发送:pthread_cond_signal(&__cond)

    3:解互斥锁:pthread_mutex_unlock(&__mutex)

    那么,这里就有一个问题,等待的时候已经加上锁了,那么我发送的时候怎么才能运行到发送函数呢?其实这是因为在pthread_cond_timedwait()函数中已经对互斥锁进行解锁操作了,所以这个时候发送信号量是不会阻塞的。其实仔细想想,这样不是才能保证同步吗?(写完代码后考虑一下)

    #include <stdio.h>
    #include <pthread.h>
    #include <string.h>
    #include <unistd.h>
    #include <semaphore.h>
    #include <sys/time.h>
     
    #define SENDSIGTIME 10
     
    pthread_cond_t g_cond;
    pthread_mutex_t g_mutex;
     
    void thread1(void *arg)
    {
        int inArg = (int)arg;
        int ret = 0;
        struct timeval now;
        struct timespec outtime;
     
        pthread_mutex_lock(&g_mutex);
     
        gettimeofday(&now, NULL);
        outtime.tv_sec = now.tv_sec + 5;
        outtime.tv_nsec = now.tv_usec * 1000;
     
        ret = pthread_cond_timedwait(&g_cond, &g_mutex, &outtime);
        //ret = pthread_cond_wait(&g_cond, &g_mutex);
        pthread_mutex_unlock(&g_mutex);
     
        printf("thread 1 ret: %d\n", ret);
     
    }
     
    int main(void)
    {
        pthread_t id1;
        int ret;
     
        pthread_cond_init(&g_cond, NULL);
        pthread_mutex_init(&g_mutex, NULL);
     
        ret = pthread_create(&id1, NULL, (void *)thread1, (void *)1);
        if (0 != ret)
        {
    	printf("thread 1 create failed!\n");
    	return 1;
        }
     
        printf("等待%ds发送信号!\n", SENDSIGTIME);
        sleep(SENDSIGTIME);
        printf("正在发送信号....\n");
        pthread_mutex_lock(&g_mutex);
        pthread_cond_signal(&g_cond);
        pthread_mutex_unlock(&g_mutex);
     
     
        pthread_join(id1, NULL);
     
        pthread_cond_destroy(&g_cond);
        pthread_mutex_destroy(&g_mutex);
     
        return 0;
    }
    

    线程等待和唤醒函数比较

     平台提供了线程等待相关函数,这些函数之间用法也有些差异:

    sleep 线程等待,等待期间线程无法唤醒。
    pthread_cond_wait  线程等待信号触发,如果没有信号触发,无限期等待下去。
    pthread_cond_timedwait  线程等待一定的时间,如果超时或有信号触发,线程唤醒。

      通过上表,可以看出pthread_cond_timedwait函数是最为灵活,使用也最为广泛。sleep的缺陷是当有紧急事件到达时,线程无法及时唤醒。pthread_cond_wait缺陷是:必须借助别的线程触发信号,否则线程自身无法唤醒,如果使用函数,线程无法处理定时任务。

      一般情况下,线程要做的工作可能有:定期处理某个事物;无事可做时,线程挂起;有事可做时,立即唤醒工作。要完成上面所述的功能,必须用pthread_cond_timedwait函数,本文介绍的就是对该函数封装。

      线程唤醒操作还涉及互斥量pthread_mutex_t,感觉与我们理解的等待和唤醒操作无关;此函数的引入,增加了理解难度。

    函数定义和接口封装如下

    //函数涉及的变量
    typedef struct ThreadSignal_T
    {
        BOOL  relativeTimespan; //是否采用相对时间
        pthread_cond_t cond;
        pthread_mutex_t mutex;
        pthread_condattr_t cattr;
    } ThreadSignal;
    
    //初始化
    void ThreadSignal_Init(ThreadSignal *signal,BOOL relativeTimespan);
    //关闭
    void ThreadSignal_Close(ThreadSignal *signal);
    //等待n毫秒
    void ThreadSignal_Wait(ThreadSignal *signal, int ms);
    //唤醒线程
    void ThreadSignal_Signal(ThreadSignal *signal);
    1)ThreadSignal_Init
    void ThreadSignal_Init(ThreadSignal *signal, BOOL relativeTimespan)
    {
        signal->relativeTimespan = relativeTimespan;
    
        pthread_mutex_init(&signal->mutex, NULL);
    
        if (relativeTimespan)
        {
            int ret = pthread_condattr_init(&signal->cattr);
            ret = pthread_condattr_setclock(&signal->cattr, CLOCK_MONOTONIC);
            ret = pthread_cond_init(&signal->cond, &signal->cattr);
        }
        else
        {
            pthread_cond_init(&signal->cond, NULL);
        }
    }

    2) ThreadSignal_Close

    void ThreadSignal_Close(ThreadSignal *signal)
    {
        if (signal->relativeTimespan)
        {
            pthread_condattr_destroy(&(signal->cattr));
        }
    
        pthread_mutex_destroy(&signal->mutex);
        pthread_cond_destroy(&signal->cond);
    }

    3) ThreadSignal_Wait

    void ThreadSignal_Wait(ThreadSignal *signal, int ms)
    {
        pthread_mutex_lock(&signal->mutex);
    
        if (signal->relativeTimespan)
        {
            //获取时间
            struct timespec outtime;
            clock_gettime(CLOCK_MONOTONIC, &outtime);
            //ms为毫秒,换算成秒
            outtime.tv_sec += ms/1000;
          
            //在outtime的基础上,增加ms毫秒
            //outtime.tv_nsec为纳秒,1微秒=1000纳秒
            //tv_nsec此值再加上剩余的毫秒数 ms%1000,有可能超过1秒。需要特殊处理
            uint64_t  us = outtime.tv_nsec/1000 + 1000 * (ms % 1000); //微秒
            //us的值有可能超过1秒,
            outtime.tv_sec += us / 1000000; 
    
            us = us % 1000000;
            outtime.tv_nsec = us * 1000;//换算成纳秒
    
            int ret = pthread_cond_timedwait(&signal->cond, &signal->mutex, &outtime);
        }
        else
        {
            struct timeval now;
            gettimeofday(&now, NULL);
    
            //在now基础上,增加ms毫秒
            struct timespec outtime;
            outtime.tv_sec = now.tv_sec + ms / 1000;
    
            //us的值有可能超过1秒
            uint64_t  us = now.tv_usec + 1000 * (ms % 1000); 
            outtime.tv_sec += us / 1000000; 
    
            us = us % 1000000;
            outtime.tv_nsec = us * 1000;
    
            int ret = pthread_cond_timedwait(&signal->cond, &signal->mutex, &outtime);
        }
        pthread_mutex_unlock(&signal->mutex);
    }

    struct timespec outtime;结构中有两个值:tv_sec ,tv_usec 。分别是秒和纳秒。等待一段时间就是:在这两个值上增加一定的数值。tv_usec 此值有范围限制的,就是不能超过1秒暨1000000000纳秒。如果超出1秒,就要在tv_sec 此值增加一秒;tv_usec 减去一秒。笔者是在实践中发现此问题的,不是无中生有。如果tv_usec 此值溢出,调用pthread_cond_timedwait函数,会立马返回。

    4)ThreadSignal_Signal

    void ThreadSignal_Signal(ThreadSignal *signal)
    {
        pthread_mutex_lock(&signal->mutex);
        pthread_cond_signal(&signal->cond);
        pthread_mutex_unlock(&signal->mutex);
    }

     

    展开全文
  • 线程等待唤醒

    2018-03-23 17:05:19
    线程等待唤醒 标签: 多线程 基本方法简介 所有的等待和唤醒线程,都是针对某个具体对象实例的. API接口 说明 wait() 让当前线程进入等待(阻塞)状态,直到其他线程调用此对象的notify()或...

    线程等待与唤醒

    标签: 多线程


    基本方法简介

    所有的等待和唤醒线程,都是针对某个具体对象实例的.

    API接口 说明
    wait() 让当前线程进入等待(阻塞)状态,直到其他线程调用此对象的notify()或notifyAll()来唤醒,之后该线程进入就绪状态.
    wait(long timeout) 让当前线程进入阻塞状态,直到其他线程唤醒此线程或者超过指定时间,之后该线程进入就绪状态
    wait(long timeout,int nanos) 让当前线程进入阻塞状态,直到其他线程唤醒此线程或者超过指定时间或者超过某个实际时间,之后该线程进入就绪状态
    notify() 唤醒该对象上的指定单个线程
    notifyAll() 唤醒该对象上的所有线程

    wait() and notify() demo

    package cn.kkcoder.thread;
    
    public class WaitAndNotify {
    
        public static void main(String[] args) throws InterruptedException {
    
            notifyThread t = new notifyThread("t1");
    
            synchronized(t) {
    
                System.out.println(Thread.currentThread().getName() + " .start()");
                t.start();
    
                System.out.println(Thread.currentThread().getName() + "  .wait()");
                t.wait();
    
                System.out.println(Thread.currentThread().getName() + " .结束");
            }
    
        }
    
    }
    class notifyThread extends Thread{
    
        public notifyThread(String name) {
            super(name);
        }
    
        @Override
        public void run() {
            synchronized(this) {
                System.out.println(Thread.currentThread().getName() + "  call notify()");
                notify();
            }
    
        }
    
    }
    控制台:
    main .start()
    main  .wait()
    t1  call notify()
    main .结束
    

    总结: wait() 方法是指让当前线程等待,并释放对象锁, 而此时的当前线程是 主线程,因为主线程获取了对象 t 的锁,t.start()之后,新建线程t1,并进入就绪状态,但是此时锁在 main 线程中,所以t1的run方法不执行,当t.wait()之后,当前线程(即主线程)进入等待(阻塞)状态,并释放t线程锁,于是执行run方法,唤醒等待的main线程,并且线程t1释放锁进入死亡状态.main线程继续执行.


    tips:wait()指当先线程进入等待状态.
    

    wait() and notifyAll() demo

    package cn.kkcoder.thread;
    
    public class NotifyAll {
    
        static Object obj = new Object();
    
        public static void main(String[] args) {
    
            NotifyAllClass t1 = new NotifyAllClass("t1");
            NotifyAllClass t2 = new NotifyAllClass("t2");
            NotifyAllClass t3 = new NotifyAllClass("t3");
    
            t1.start();
            t2.start();
            t3.start();
    
            try {
                System.out.println(Thread.currentThread().getName() + " sleep 3000 ms");
                Thread.currentThread().sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + " 唤醒所有线程");
                obj.notifyAll();
            }
    
        }
    
    
        static class NotifyAllClass extends Thread{
    
            public NotifyAllClass(String name) {
                super(name);
            }
    
            @Override
            public void run() {
    
                synchronized (obj) {
                    try {
                        System.out.println(Thread.currentThread().getName() + " 执行 wait ");
                        obj.wait();
                        System.out.println(Thread.currentThread().getName() + "继续 执行");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    
    控制台:
    main sleep 3000 ms
    t1 执行 wait 
    t3 执行 wait 
    t2 执行 wait 
    main 唤醒所有线程
    t2继续 执行
    t3继续 执行
    t1继续 执行
    

    t1,t2,t3和主线程 分别执行, t1,t2,t3线程分别 持有ojb对象,并执行了等待,并释放各自的锁,都进入阻塞状态,主线程(mian)线程 sleep 之后,获取obj对象的锁,执行notifyAll,唤醒所有线程.t1,t2,t3之后并执行结束,释放obj的同步锁,之后被唤醒并继续执行.


    最后: notify() 和 wait() 等方法依赖于 同步锁 ,同步锁依赖于 对象,所以,这些方法也是依赖于 对象 的.


    yield() demo

    package cn.kkcoder.thread;
    
    public class YieldTet {
    
        static Object obj = new Object();
    
        public static void main(String[] args) {
            TestYield t1 = new TestYield("t1");
            TestYield t2 = new TestYield("t2");
    
            t1.start();
            t2.start();
        }
    
        static class TestYield extends Thread{
            public TestYield(String name) {
                super(name);
            }
    
            @Override
            public void run() {
    
                synchronized(obj) {
                    for(int i=0;i<=5;i++) {
    
                        System.out.println(Thread.currentThread().getName() + " i = " + i);
    
                        if(i%3==0) {
                            System.out.println(Thread.currentThread().getName() + " 执行yield");
                            Thread.yield();
                        }
                    }
                }
            }
        }
    }
    
    控制台:
    t1 i = 0
    t1 执行yield
    t1 i = 1
    t1 i = 2
    t1 i = 3
    t1 执行yield
    t1 i = 4
    t1 i = 5
    t2 i = 0
    t2 执行yield
    t2 i = 1
    t2 i = 2
    t2 i = 3
    t2 执行yield
    t2 i = 4
    t2 i = 5
    

    yield() 方法会进行让步,但不会释放同步锁.即yield会把该线程从运行状态,转换到 就绪状态.

    展开全文
  • C++大量线程等待唤醒

    千次阅读 2020-06-20 18:01:36
    线程等待和唤醒使用条件变量condition_variable锁mutex结合实现,其中条件变量提供了wait(), notify(), notifyAll()等方法。 wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的...

    一、线程唤醒方法

    • C++11之后提供了thread线程类,可以很方便的编写多线程程序。线程的等待和唤醒使用条件变量condition_variable和锁mutex结合实现,其中条件变量提供了wait(), notify(), notifyAll()等方法。
    • wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。而notify()和notifyAll()的作用,则是唤醒当前条件变量上的等待线程;notify()是随机唤醒单个等待的线程,而notifyAll()是唤醒所有等待的线程。

    二、线程唤醒方式比较

    线程唤醒需要依靠锁和条件变量实现,那么是每个线程拥有自己独立的锁和条件变量性能高,还是共用锁和条件变量性能高呢?下面对其进行测试。

    1.测试环境

    • 操作系统:windows 10 64bit
    • CPU:2个内核,4个逻辑处理器
    • 编译器:MinGW 7.3.0 64-bit
    • 测试线程数:3000个(每个线程唤醒立刻又进入等待状态)

    2.测试结果

    1. 每个线程拥有独立的锁、独立的条件变量,即代码中的方式一。使用notify_one唤醒线程。
      在这里插入图片描述
    2. 所有线程共用同一个锁,但每个线程拥有独立的条件变量,即代码中的方式二。使用notify_one唤醒线程。
      在这里插入图片描述
    3. 所有的线程共用同一个锁,同一个条件变量,通过bool数组区分需要唤醒的线程。由于同一个条件变量,所以所有等待的线程处于同一等待队列,使用notify_one随机唤醒一个线程会出现无法唤醒的状态,所有使用notify_all唤醒所有等待的线程。然后根据数组区分具体需要唤醒的线程。
      在这里插入图片描述

    3.结果分析

    从以上三种测试结果看出,方式一和方式二无明显差别,方式三出现CPU负荷高的情况。其原因为方式三中所有等待的线程在同一等待队列,唤醒某个线程时,必须通知所有线程才能确保需要的线程被唤醒,即使用notify_all唤醒线程,此时出现了惊群效应。由于本测试程序频繁唤醒线程,所以CPU占用持续居高。

    惊群效应,即当某一资源可用时,多个进程/线程会惊醒,竞争资源,导致n-1个进程/线程做了无效的调度,上下文切换,cpu瞬时增高。

    三、测试代码

    #include <thread>
    #include <mutex>
    #include <condition_variable>
    #include <sstream>
    #include <vector>
    
    #define WAY 2 //设置唤醒线程方式
    
    #if WAY == 1 //方式1,每个线程拥有独立的锁和条件变量
    class ThreadCtrl
    {
    public:
        ThreadCtrl()
            :m_flag(false)
        {}
        void wait()
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            m_cv.wait(lock, [=]{ return m_flag; });
            m_flag = false;
        }
        void wake()
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            m_flag = true;
            m_cv.notify_one();
        }
    private:
        std::mutex m_mutex;
        std::condition_variable m_cv;
        bool m_flag;
    };
    
    class ThreadManage
    {
    public:
        ThreadManage(){}
        ~ThreadManage()
        {
            for (auto ctrl : m_CtrlVec)
                delete ctrl;
            m_CtrlVec.clear();
        }
        ThreadCtrl* createCtrl()
        {
            auto ctrl = new ThreadCtrl();
            m_mutex.lock();
            m_CtrlVec.push_back(std::move(ctrl));
            m_mutex.unlock();
            return ctrl;
        }
        std::vector<ThreadCtrl*>& getAllCtrl() { return m_CtrlVec; }
    private:
        std::vector<ThreadCtrl*> m_CtrlVec;
        std::mutex m_mutex;
    };
    #elif WAY == 2 //方式2,所有线程共用同一锁,但每个线程拥有独立的条件变量
    class ThreadCtrl
    {
    public:
        ThreadCtrl(std::mutex* mutex)
            :m_mutex(mutex), m_flag(false)
        {}
        void wait()
        {
            std::unique_lock<std::mutex> lock(*m_mutex);
            m_cv.wait(lock, [=]{ return m_flag; });
            m_flag = false;
        }
        void wake()
        {
            std::unique_lock<std::mutex> lock(*m_mutex);
            m_flag = true;
            m_cv.notify_one();
        }
    private:
        std::mutex* m_mutex;
        std::condition_variable m_cv;
        bool m_flag;
    };
    
    class ThreadManage
    {
    public:
        ThreadManage(){}
        ~ThreadManage()
        {
            for (auto ctrl : m_CtrlVec)
                delete ctrl;
            m_CtrlVec.clear();
        }
        ThreadCtrl* createCtrl()
        {
            auto ctrl = new ThreadCtrl(&m_wakeMutex);
            m_mutex.lock();
            m_CtrlVec.push_back(std::move(ctrl));
            m_mutex.unlock();
            return ctrl;
        }
        std::vector<ThreadCtrl*>& getAllCtrl() { return m_CtrlVec; }
    private:
        std::vector<ThreadCtrl*> m_CtrlVec;
        std::mutex m_mutex;
        std::mutex m_wakeMutex;
    };
    #elif WAY == 3 //方式3,所有的线程共用同一锁和同一条件变量
    class ThreadCtrl
    {
    public:
        ThreadCtrl(std::mutex* mutex, std::condition_variable* cv, bool* flag)
            :m_mutex(mutex), m_cv(cv), m_flag(flag)
        {}
        void wait()
        {
            std::unique_lock<std::mutex> lock(*m_mutex);
            m_cv->wait(lock, [=]{ return *m_flag; });
            *m_flag = false;
        }
        void wake()
        {
            std::unique_lock<std::mutex> lock(*m_mutex);
            *m_flag = true;
            m_cv->notify_all();//所有线程共用条件变量,所以必须通知所有等待的线程
        }
    private:
        std::mutex* m_mutex;
        std::condition_variable* m_cv;
        bool* m_flag;
    };
    
    class ThreadManage
    {
    public:
        ThreadManage(){}
        ~ThreadManage()
        {
            for (auto ctrl : m_CtrlVec)
                delete ctrl;
            m_CtrlVec.clear();
        }
        ThreadCtrl* createCtrl()
        {
            auto flag = new bool(false);
            auto ctrl = new ThreadCtrl(&m_wakeMutex, &m_cv, flag);
            m_mutex.lock();
            m_flagVec.push_back(std::move(flag));
            m_CtrlVec.push_back(std::move(ctrl));
            m_mutex.unlock();
            return ctrl;
        }
        std::vector<ThreadCtrl*>& getAllCtrl() { return m_CtrlVec; }
    private:
        std::vector<ThreadCtrl*> m_CtrlVec;
        std::mutex m_mutex;
        std::mutex m_wakeMutex;
        std::condition_variable m_cv;
        std::vector<bool*> m_flagVec;
    };
    #endif
    
    //线程ID转为数字
    long long threadIdToNumber(const std::thread::id& id)
    {
        std::stringstream oss;
        oss << id;
        return std::stoll(oss.str());
    }
    
    //测试线程内执行的函数
    void fun(ThreadCtrl* ctrl)
    {
        while (true)
        {
            ctrl->wait();//睡眠
    #if 0
            auto tid = std::this_thread::get_id();
            auto lid = threadIdToNumber(tid);
            printf("Thread ID: %lld\n", lid);
    #endif
        }
    }
    
    //负责唤醒其它线程
    void wakeFun(ThreadManage* manage)
    {
        std::vector<ThreadCtrl*> allCtrl = manage->getAllCtrl();
        const int num = allCtrl.size();
        int id = num - 1;
        while (true)
        {
            allCtrl[id]->wake();//唤醒
            id--;
            if (id < 0) id = num - 1;
            //等待1ms,尽可能确保所有线程处于等待状态
            std::this_thread::sleep_for(std::chrono::milliseconds(1));
        }
    }
    
    int main()
    {
        // 测试线程个数
        constexpr const int count = 3000;
        // 创建线程管理,管理线程唤醒
        auto manage = new ThreadManage;
        // 创建测试线程
        std::vector<std::thread> threadVec(count);
        for (int i = 0; i < count; i++) {
            auto ctrl = manage->createCtrl();
            threadVec[i] = std::thread(fun, ctrl);
        }
        std::thread wakeThread(wakeFun, manage);
        // 等待子线程
        for (int i = 0; i < count; i++)
            threadVec[i].join();
        wakeThread.join();
        // 释放资源
        delete manage;
    }
    

    测试中线程数为3000个,此时必须为64位程序才能正常运行,32位会出现无法正常启动的情况。

    展开全文
  • java线程等待和唤醒

    2018-12-26 22:34:53
    notify() :唤醒在此对象监视器上等待的单个线程。 notifyAll() : 唤醒在此对象监视器上等待的所有线程。 wait():让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() ...
  • java 多线程—— 线程等待唤醒

    千次阅读 2017-02-21 13:43:29
    第1部分 wait(), notify(), notifyAll()等方法介绍  在Object.java中,定义了wait(), notify()notifyAll()等...而notify()notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而no
  • Java多线程--线程等待唤醒

    千次阅读 2016-06-23 10:24:41
    wait(), notify(), notifyAll()等方法介绍 在Object.java中,定义了wait(), notify()notifyAll()等接口。...而notify()notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()
  • java 线程等待唤醒

    千次阅读 2014-08-09 17:31:02
    本章,会对线程等待/唤醒方法进行介绍。涉及到的内容包括: 1. wait(), notify(), notifyAll()等方法介绍 2. wait()notify() 3. wait(long timeout)notify() 4. wait() notifyAll() 5. 为什么notify(), wait...
  • java 中waitnotify 线程等待和线程唤醒的使用方式 需要借助synchronized
  • java多线程等待唤醒,以及线程同步。  在Object.java中,定义了wait(), notify()notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。而notify()...
  • 概要本章,会对线程等待/唤醒方法进行介绍。1. wait(), notify(), notifyAll()等方法介绍 在Object.java中,定义了wait(), notify()notifyAll()等接口。  wait()的作用是让当前线程进入等待状态,同时,wait()...
  • 要想实现多个线程之间的协同,如:线程执行先后顺序、获取某个线程执行的结果等等。 涉及到线程之间相互通信,分为下面四类: 1 文件共享 2 网络共享 socket编程问题,非本文重点,不再赘述 3 共享变量 4 线程协作 - ...
  • 线程等待唤醒机制

    千次阅读 2017-05-09 11:03:26
    为了避免此类问题,我们会用到线程间的通信,而等待唤醒机制,就是线程间通信的一种形式。 等待唤醒机制用到的方法主要有: public final void wait() throws InterruptedException : 当前线程
  • 第二部分 线程等待和唤醒

    万次阅读 2011-01-13 14:24:00
    使线程陷入等待实际上是暂时剥夺线程当前拥有的CPU时间片获取CPU时间片的资格,使其返回到就绪状态。除非被唤醒,否则等待时间已满,该线程将一直等待。不会被JVM线程调度器选中并赋予CPU时间片。处于等待线程...
  • 线程等待唤醒机制

    千次阅读 2015-11-18 17:52:13
    ( 1 )等待唤醒机制就是用于解决线程间通信的问题的,使用到的3个方法的含义如下: wait:告诉当前线程放弃执行权,并放弃监视器(锁)并进入阻塞状态,直到其他线程持有获得执行权,并持有了相同的监视器(锁)并...
  • Java线程等待唤醒机制(加深理解)

    万次阅读 多人点赞 2019-08-04 16:28:06
    这里就用到了线程等待唤醒机制,下面具体看一下。 等待唤醒机制示例 下面代码是一个简单的线程唤醒机制示例,主要就是在Activity启动的时候初始化并start线程,线程start后会进入等待状态,在onResume方法中执行...
  • Java——设置线程等待与线程唤醒

    千次阅读 2017-10-10 14:49:24
    //线程间的通信:线程的任务...指明让持有哪个锁的线程等待或被唤醒 */ //还是上次的例子,实现存一个输出一个,而不是输出一大堆//描述数据 class Res{ String name; String sex; //加一个flag标记,false表示没
  • java 多线程等待唤醒机制实例

    千次阅读 2016-10-26 12:46:53
    例子: 1、实体类 public class Student {  String name;  int age;  boolean flag = false; // 表示没有值 ...2、线程1 public class SetThread implements Runnable {  private Student s;  private
  • 线程等待唤醒机制

    千次阅读 2018-04-26 16:00:18
    简介什么叫做等待唤醒机制呢?举一个栗子,请看下图:当我们开启两条线程时,一条线程专门输入数据,另条取数据。并且要实现,输入一个数据过后,另一方取出一个数据。在多线程的情况下,当输入线程抢到CPU的执行权...
  • Java-线程Thread等待唤醒

    千次阅读 2017-03-29 17:13:37
    Java线程等待唤醒主要包括几个方法:(1)notify():唤醒在此对象监视器上等待的单个线程。(2)notifyAll():唤醒在此对象监视器上等待的所有线程。(3)wait():让当前线程处于阻塞状态,同时释放它所持有的锁...
  • 生产者消费者案例分析: 经典的生产者消费者案例(Producer/Consumer):  分析案例:  1):生产者消费者应该操作共享的资源(实现方式来做).  2):使用一个或多个线程来表示生产者(Producer).  3):使用一个...
  • wait()notify()示例3. wait(long timeout)notify()4. wait() notifyAll()5. 为什么notify(), wait()等函数定义在Object中,而不是Thread中 1. wait(), notify(), notifyAll()等方法介绍  ...
  • 线程wait等待和notify唤醒

    千次阅读 2012-04-11 16:48:52
    /**  * 测试waitnotify方法 ... * 等待是当前线程对对象等待唤醒线程等待对象的所有线程唤醒(可随机唤醒一个,可唤醒所有的)  * @author sam 2012-4-11  */ public class TestWai
  • 功能:唤醒等待QWaitCondition的线程中的一个线程。 *注意:这里我暂且还不能分清wakeAll()wakeOne()的区别 例子1:消费者生产者 要点: (1)生产者必须检查缓冲是否已满(numUsedBytes == Buffer...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 169,099
精华内容 67,639
关键字:

线程等待和唤醒