精华内容
下载资源
问答
  • zircon的两种调度理解

    万次阅读 2019-07-06 17:22:49
    zircon 实现两种调度机制,一种就是fair 其实现在fair_scheduler.cpp中,一种是基于时间片的其实现在sched.cpp 中,调度器的入口都在sche_reschedule()这个函数中。 例如fair的实现如下: void sched_reschedule() {...
    zircon 实现两种调度机制,一种就是fair 其实现在fair_scheduler.cpp中,一种是基于时间片的其实现在sched.cpp 中,调度器的入口都在sche_reschedule()这个函数中。
    例如fair的实现如下:
    void sched_reschedule() {
        FairScheduler::Reschedule();
    }
    fair的实现是一个cpp的类。
    另一中sche_reschedule()的实现在sched.cpp 中,我们简单看下
    void sched_reschedule() {
       
       
        current_thread->state = THREAD_READY;
    
        // idle thread doesn't go in the run queue
        if (likely(!thread_is_idle(current_thread))) {
    
    #可见会首先判断当前线程的时间片是否用尽,用尽的话,则加入到当前cpu 运行队列的末尾,否则就插入到head,这样下次调用这个函数的时候就会
    优先调用这个函数  
            if (current_thread->remaining_time_slice > 0) {
                insert_in_run_queue_head(curr_cpu, current_thread);
            } else {
                insert_in_run_queue_tail(curr_cpu, current_thread);
            }
        }
    
        sched_resched_internal();
    }
    void sched_resched_internal() {
        thread_t* current_thread = get_current_thread();
        uint cpu = arch_curr_cpu_num();
    
        
        CPU_STATS_INC(reschedules);
    
        // pick a new thread to run
    #从当前cpu 挑选一个thread 来运行,类似于linux的RR调度
        thread_t* newthread = sched_get_top_thread(cpu);
    
        DEBUG_ASSERT(newthread);
    
        newthread->state = THREAD_RUNNING;
    
        thread_t* oldthread = current_thread;
        oldthread->preempt_pending = false;
    
        
    #计算久进程的时间记账
        zx_time_t now = current_time();
    
        // account for time used on the old thread
        DEBUG_ASSERT(now >= oldthread->last_started_running);
        zx_duration_t old_runtime = zx_time_sub_time(now, oldthread->last_started_running);
        oldthread->runtime_ns = zx_duration_add_duration(oldthread->runtime_ns, old_runtime);
        oldthread->remaining_time_slice = zx_duration_sub_duration(
            oldthread->remaining_time_slice, MIN(old_runtime, oldthread->remaining_time_slice));
    
        // set up quantum for the new thread if it was consumed
        if (newthread->remaining_time_slice == 0) {
            newthread->remaining_time_slice = THREAD_INITIAL_TIME_SLICE;
        }
    
        newthread->last_started_running = now;
    #切换mmu
        // see if we need to swap mmu context
        if (newthread->aspace != oldthread->aspace) {
            vmm_context_switch(oldthread->aspace, newthread->aspace);
        }
    #进程切换
        // do the low level context switch
        final_context_switch(oldthread, newthread);
    }

     

    展开全文
  • 本文介绍APScheduler最基本的用法“定时几秒后启动job”,解释其中两种调度器BackgroundScheduler和BlockingScheduler的区别,说明了如何做到“让job在start()后就开始运行”,详述“job执行时间大于定时调度时间”...

    摘要

    本文介绍APScheduler最基本的用法“定时几秒后启动job”,解释其中两种调度器BackgroundSchedulerBlockingScheduler的区别,说明了如何做到“让job在start()后就开始运行”,详述“job执行时间大于定时调度时间”这种特殊情况的问题及解决方法,并说明了每个job都会以thread的方式被调度。

    基本的定时调度

    APScheduler是python的一个定时任务调度框架,能实现类似linux下crontab类型的任务,使用起来比较方便。它提供基于固定时间间隔、日期以及crontab配置类似的任务调度,并可以持久化任务,或将任务以daemon方式运行。

    下面是一个最基本的使用示例:

    from apscheduler.schedulers.blocking import BlockingScheduler
    
    def job():
        print('job 3s')
    
    
    if __name__=='__main__':
    
        sched = BlockingScheduler(timezone='MST')
        sched.add_job(job, 'interval', id='3_second_job', seconds=3)
        sched.start()
    

    它能实现每隔3s就调度job()运行一次,所以程序每隔3s就输出’job 3s’。通过修改add_job()的参数seconds,就可以改变任务调度的间隔时间。

    BlockingSchedulerBackgroundScheduler区别

    APScheduler中有很多种不同类型的调度器,BlockingSchedulerBackgroundScheduler是其中最常用的两种调度器。那他们之间有什么区别呢? 简单来说,区别主要在于BlockingScheduler会阻塞主线程的运行,而BackgroundScheduler不会阻塞。所以,我们在不同的情况下,选择不同的调度器:

    • BlockingScheduler: 调用start函数后会阻塞当前线程。当调度器是你应用中唯一要运行的东西时(如上例)使用。
    • BackgroundScheduler: 调用start后主线程不会阻塞。当你不运行任何其他框架时使用,并希望调度器在你应用的后台执行。

    下面用两个例子来更直观的说明两者的区别。

    • BlockingScheduler的真实例子
    from apscheduler.schedulers.blocking import BlockingScheduler
    import time
    
    def job():
        print('job 3s')
    
    
    if __name__=='__main__':
    
        sched = BlockingScheduler(timezone='MST')
        sched.add_job(job, 'interval', id='3_second_job', seconds=3)
        sched.start()
    
        while(True):
            print('main 1s')
            time.sleep(1)
    

    运行这个程序,我们得到如下的输出:

    job 3s
    job 3s
    job 3s
    job 3s

    可见,BlockingScheduler调用start函数后会阻塞当前线程,导致主程序中while循环不会被执行到。

    • BackgroundScheduler的真实例子
    from apscheduler.schedulers.background import BackgroundScheduler
    import time
    
    def job():
        print('job 3s')
    
    
    if __name__=='__main__':
    
        sched = BackgroundScheduler(timezone='MST')
        sched.add_job(job, 'interval', id='3_second_job', seconds=3)
        sched.start()
    
        while(True):
            print('main 1s')
            time.sleep(1)
    

    可见,BackgroundScheduler调用start函数后并不会阻塞当前线程,所以可以继续执行主程序中while循环的逻辑。

    main 1s
    main 1s
    main 1s
    job 3s
    main 1s
    main 1s
    main 1s
    job 3s

    通过这个输出,我们也可以发现,调用start函数后,job()并不会立即开始执行。而是等待3s后,才会被调度执行。

    如何让job在start()后就开始运行

    如何才能让调度器调用start函数后,job()就立即开始执行呢?

    其实APScheduler并没有提供很好的方法来解决这个问题,但有一种最简单的方式,就是在调度器start之前,就运行一次job(),如下

    from apscheduler.schedulers.background import BackgroundScheduler
    import time
    
    def job():
        print('job 3s')
    
    
    if __name__=='__main__':
        job()
        sched = BackgroundScheduler(timezone='MST')
        sched.add_job(job, 'interval', id='3_second_job', seconds=3)
        sched.start()
    
        while(True):
            print('main 1s')
            time.sleep(1)

    这样就能得到如下的输出

    job 3s
    main 1s
    main 1s
    main 1s
    job 3s
    main 1s
    main 1s
    main 1s

    这样虽然没有绝对做到“让job在start()后就开始运行”,但也能做到“不等待调度,而是刚开始就运行job”。

    如果job执行时间过长会怎么样

    如果执行job()的时间需要5s,但调度器配置为每隔3s就调用一下job(),会发生什么情况呢?我们写了如下例子:

    from apscheduler.schedulers.background import BackgroundScheduler
    import time
    
    def job():
        print('job 3s')
        time.sleep(5)
    
    if __name__=='__main__':
    
        sched = BackgroundScheduler(timezone='MST')
        sched.add_job(job, 'interval', id='3_second_job', seconds=3)
        sched.start()
    
        while(True):
            print('main 1s')
            time.sleep(1)
    

    运行这个程序,我们得到如下的输出:

    main 1s
    main 1s
    main 1s
    job 3s
    main 1s
    main 1s
    main 1s
    Execution of job "job (trigger: interval[0:00:03], next run at: 2018-05-07 02:44:29 MST)" skipped: maximum number of running instances reached (1)
    main 1s
    main 1s
    main 1s
    job 3s
    main 1s

    可见,3s时间到达后,并不会“重新启动一个job线程”,而是会跳过该次调度,等到下一个周期(再等待3s),又重新调度job()。

    为了能让多个job()同时运行,我们也可以配置调度器的参数max_instances,如下例,我们允许2个job()同时运行:

    from apscheduler.schedulers.background import BackgroundScheduler
    import time
    
    def job():
        print('job 3s')
        time.sleep(5)
    
    if __name__=='__main__':
        job_defaults = { 'max_instances': 2 }
        sched = BackgroundScheduler(timezone='MST', job_defaults=job_defaults)
        sched.add_job(job, 'interval', id='3_second_job', seconds=3)
        sched.start()
    
        while(True):
            print('main 1s')
            time.sleep(1)

    运行程序,我们得到如下的输出:

    main 1s
    main 1s
    main 1s
    job 3s
    main 1s
    main 1s
    main 1s
    job 3s
    main 1s
    main 1s
    main 1s
    job 3s

    每个job是怎么被调度的

    通过上面的例子,我们发现,调度器是定时调度job()函数,来实现调度的。

    那job()函数会被以进程的方式调度运行,还是以线程来运行呢?

    为了弄清这个问题,我们写了如下程序:

    from apscheduler.schedulers.background import BackgroundScheduler
    import time,os,threading
    
    def job():
        print('job thread_id-{0}, process_id-{1}'.format(threading.get_ident(), os.getpid()))
        time.sleep(50)
    
    if __name__=='__main__':
        job_defaults = { 'max_instances': 20 }
        sched = BackgroundScheduler(timezone='MST', job_defaults=job_defaults)
        sched.add_job(job, 'interval', id='3_second_job', seconds=3)
        sched.start()
    
        while(True):
            print('main 1s')
            time.sleep(1)

    运行程序,我们得到如下的输出:

    main 1s
    main 1s
    main 1s
    job thread_id-10644, process_id-8872
    main 1s
    main 1s
    main 1s
    job thread_id-3024, process_id-8872
    main 1s
    main 1s
    main 1s
    job thread_id-6728, process_id-8872
    main 1s
    main 1s
    main 1s
    job thread_id-11716, process_id-8872

    可见,每个job()的进程ID都相同,但线程ID不同。所以,job()最终是以线程的方式被调度执行。

    参考

    展开全文
  • linux work queue的两种调度方式

    千次阅读 2016-09-25 17:26:15
    第一使用schedule_work手动调度: #include linux/init.h> #include linux/module.h> #include linux/timer.h> #include linux/time.h> #include linux/workqueue.h> #include asm/atomic.h> #includ

    第一种使用schedule_work手动调度:

    #include<linux/init.h>
    #include<linux/module.h>
    #include<linux/timer.h>
    #include<linux/time.h>
    #include<linux/workqueue.h>
    #include<asm/atomic.h>
    #include<linux/delay.h>

    MODULE_AUTHOR("lcw");
    MODULE_LICENSE("GPL");

    struct timer_data test_data;
    struct timer_data test_data1;
    static struct workqueue_struct*test_workqueue;
    atomic_t wq_run_times;
    unsigned int failed_cnt = 0;


    static void do_work(void*);
    static void do_work1(void*);

    static struct work_struct test_work;
    static struct work_struct test_work1;


    // 工作函数中再次手动调度队列,使其不断执行
    static void do_work(void*arg)   
    {
        printk("goodbye\n");
        mdelay(2000);
        schedule_work(&test_work1);
    }

    static void do_work1(void*arg)
    {
        printk("hello world\n");
        mdelay(2000);
        schedule_work(&test_work);
    }
    int wq_init(void)
    {
        INIT_WORK(&test_work, do_work);
        INIT_WORK(&test_work1, do_work1)

        test_workqueue = create_singlethread_workqueue("test-wq");
        schedule_work(&test_work);
        printk("test-wq init success\n");
        printk("jiffies: %lu\n", jiffies);

        return 0;
    }

    void wq_exit(void)
    {
        destroy_workqueue(test_workqueue);
        printk("wq exit success\n");
    }

    module_init(wq_init);
    module_exit(wq_exit);


    第二种使用queue_work和定时器自动调度:

    #include linux/init.h>
    #include linux/module.h>
    #include linux/moduleparam.h>
    #include linux/time.h>
    #include linux/timer.h>
    #include linux/workqueue.h>
    #include asm/atomic.h>
    MODULE_AUTHOR("lcw");
    MODULE_LICENSE("GPL");


    struct timer_data {
            struct timer_list timer;
            struct workqueue_struct *work_queue;
            unsigned long prev_jiffies;
            unsigned int loops;
    };


    static struct timer_list timer1;
    static struct timer_list timer2;


    static void do_work(void *);
    static DECLARE_WORK(test_work, do_work, NULL);
    static DECLARE_WORK(test_work1, do_work, NULL);
    static struct workqueue_struct *test_workqueue;
    atomic_t wq_run_times;
    unsigned int failed_cnt = 0;




    // 定时器1超时函数
    void test_timer_fn1(unsigned long arg)
    {
            struct timer_data *data = (struct timer_data *)arg;


          mod_timer(&timer1, jiffies+HZ/100); // 设置超时时间 1\100s 




            if (queue_work(test_workqueue, &test_work)== 0) {
                    printk("Timer (0) add work queue failed\n");
                    (*(&failed_cnt))++;
            }
            data->loops++;
            printk("timer-0 loops: %u\n", data->loops);
    }




    // 定时器2超时函数
    void test_timer_fn2(unsigned long arg)
    {
            struct timer_data *data = (struct timer_data *)arg;


            mod_timer(&timer2, jiffies+HZ/100); // 设置超时时间 1\100s 




            //if (queue_work(test_workqueue, &test_work)== 0) {
            if (queue_work(test_workqueue, &test_work1)== 0) {
                    printk("Timer (1) add work queue failed\n");
                    (*(&failed_cnt))++;
            }
            data->loops++;
            printk("timer-1 loops: %u\n", data->loops);
    }






    // work func
    void do_work(void*arg)
    {
            //原子计数值加一
            atomic_inc(&wq_run_times);
            printk("====work queue run times: %u====\n", atomic_read(&wq_run_times));
            printk("====failed count: %u====\n",*(&failed_cnt));
    }










    // init
    int wq_init(void)
    {


    //原子计数值初始化
            atomic_set(&wq_run_times, 0);


    // work queue        
            test_workqueue = create_singlethread_workqueue("test-wq");


    // timer1
            init_timer(&timer1);
            timer1.function= test_timer_fn1;
            add_timer(&timer1);
            


    // timer2
            init_timer(&timer2);
            timer2.function= test_timer_fn1;
            add_timer(&timer2);


    //设置超时时间,启动定时器
           mod_timer(&timer1, jiffies+HZ/100); // 设置超时时间 1\100s 
          mod_timer(&timer2, jiffies+HZ/100); // 设置超时时间 1\100s 




            return 0;
    }


    void wq_exit(void)
    {
            del_timer(&test_data.timer);
            del_timer(&test_data1.timer);
            destroy_workqueue(test_workqueue);
            printk("wq exit success\n");
    }


    module_init(wq_init);
    module_exit(wq_exit)

    注意:不能在同一时间内向一个工作队列添加相同的任务
    展开全文
  • 1、Spring调度两种方式 Spring提供了两种后台任务的方法,分别是: 调度任务,@Schedule 异步任务,@Async 当然,使用这两个是有条件的,需要在spring应用的上下文中声明 <task:annotation-driven/>当然,...

    1、Spring调度的两种方式

    Spring提供了两种后台任务的方法,分别是:
        调度任务,@Schedule
        异步任务,@Async
    当然,使用这两个是有条件的,需要在spring应用的上下文中声明
    <task:annotation-driven/>当然,如果我们是基于java配置的,需要在配置哪里加多EnableScheduling和@EnableAsync 就像下面这样

    @EnableScheduling
    @EnableAsync
    public class WebAppConfig {
       ....
    }

    除此之外,还是有第三方库可以调用的,例如Quartz.

    2、@Schedule

    先看下@Schedule怎么调用再说

    public final static long ONE_DAY = 24 * 60 * 60 * 1000;
    public final static long ONE_HOUR = 60 * 60 * 1000;
     
    @Scheduled(fixedRate = ONE_DAY)
    public void scheduledTask() {
       System.out.println(" 我是一个每隔一天就会执行一次的调度任务");
    }
     
    @Scheduled(fixedDelay = ONE_HOURS)
    public void scheduleTask2() {
        System.out.println(" 我是一个执行完后,隔一小时就会执行的任务");
    }
     
    @Scheduled(initialDelay=1000, fixedRate=5000)
    public void doSomething() {
        // something that should execute periodically
    }
     
    @Scheduled(cron = "0 0/1 * * * ? ")
    public void ScheduledTask3() {
        System.out.println(" 我是一个每隔一分钟就就会执行的任务");
    }

    需要注意的

    1.     关于最后一个,在指定时间执行的任务,里面使用的是Cron表达式,同时我们看到了两个不一样的面孔fixedDelay& fixedRate,前者fixedDelay表示在指定间隔运行程序,例如这个程序在今晚九点运行程序,跑完这个方法后的一个小时,就会再执行一次,而后者fixedDelay者是指,这个函数每隔一段时间就会被调用(我们这里设置的是一天),不管再次调度的时候,这个方法是在运行还是结束了。而前者就要求是函数运行结束后开始计时的,这就是两者区别。
    2.     这个还有一个initialDelay的参数,是第一次调用前需要等待的时间,这里表示被调用后的,推迟一秒再执行,这适合一些特殊的情况。
    3.     我们在serviceImpl类写这些调度任务时候,也需要在这些我们定义的serviceInterface的借口中写多这个接口,要不然会爆 but not found in any interface(s) for bean JDK proxy.Either pull the method up to an interface or

    3、@Async

    有时候我们会调用一些特殊的任务,任务会比较耗时,重要的是,我们不管他返回的后果。这时候我们就需要用这类的异步任务啦,调用后就让他去跑,不堵塞主线程,我们继续干别的。代码像下面这样:

    public void AsyncTask(){
     
        @Async
        public void doSomeHeavyBackgroundTask(int sleepTime) {
            try {
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
         
         
        @Async
        public Future<String> doSomeHeavyBackgroundTask() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
         
        public void printLog() {
             System.out.println(" i print a log ,time=" + System.currentTimeMillis());
        }
     
    }

    我们写个简单的测试类来测试下

    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @ContextConfiguration(classes = AsycnTaskConfig.class) //要声明@EnableASync
    public class AsyncTaskTest {
        @Autowired
        AsyncTask asyncTask;
        @Test
        public void AsyncTaskTest() throws InterruptedException {
            if (asyncTask != null) {
                asyncTask.doSomeHeavyBackgroundTask(4000);
                asyncTask.printLog();
                Thread.sleep(5000);
            }
        }
    }

    这感觉比我们手动开多一个线程方便多了,不想异步的话直接把@Async去掉就可以了,另外如果你想要返回个结果的,这需要加多个Future<>,关于这个Future,完全可以写多几篇文章介绍,顺便把FutureTask介绍了。如果想修改Spring boot的默认线程池配置,可以实现AsyncConfigurer.
    需要注意的:
        相对于@scheduled,这个可以有参数和返回个结果,因为这个是我们调用的,而调度的任务是spring调用的。
        异步方法不能内部调用,只能像上面那样,外部调用,否则就会变成阻塞主线程的同步任务啦!这个坑我居然跳下去了!例如下面这样的。

    public void AsyncTask(){
        public void fakeAsyncTaskTest(){
            doSomeHeavyBackgroundTask(4000);
            printLog();
            //你会发现,当你像这样内部调用的时候,居然是同步执行的,不是异步的!!
        }
         
        @Async
        public void doSomeHeavyBackgroundTask(int sleepTime) {
            try {
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
         
        public void printLog() {
            System.out.println(" i print a log ");
        }
     
    }
    1. 另外一点就是不要重复的扫描,这也会导致异步无效,具体的可以看这个stackoveflow的spring-async-not-working Issue。
    2. 关于异常处理,难免在这个异步执行过程中有异常发生,对于这个问题,spring提供的解决方案如下,实现 AsyncUncaughtExceptionHandler接口。
    public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable ex, Method method, Object... params) {
            // handle exception
        }
    }

    写好我们的异常处理后,我们需要配置一下,告诉spring,这个异常处理就是我们在运行异步任务时候,抛出错误时的异常终结者

    @Configuration
    @EnableAsync
    public class AsyncConfig implements AsyncConfigurer {
        @Bean
        public AsyncTask asyncBean() {
            return new AsyncTask();
        }
         
        @Override
        public Executor getAsyncExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(7);
            executor.setMaxPoolSize(42);
            executor.setQueueCapacity(11);
            executor.setThreadNamePrefix("MyExecutor-");
            executor.initialize();
            return executor;
        }
         
        @Override
        public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
             return new MyAsyncUncaughtExceptionHandler();
        }
    }

    4、Quartz登场

    处理这两个外,还有一个和spring整合的第三方库叫Quartz
    看了下官网的使用简介,也是挺逗的,现在都习惯用maven,gradle之类来关系这些依赖了,他还叫人下载,也是不知为何,详情点击->
    http://quartz-scheduler.org/documentation/quartz-2.2.x/quick-start
    估计有可能是因为没再维护了的原因吧,看了下,最新版2.2居然是Sep, 2013更新的…
    居然是停更的,不过Quartz作为一个企业级应用的任务调度框架,还是一个可以的候选项目的。
    这里不铺开讲,有兴趣就去官网看下吧。整体用起来感觉是没有spring自己的后台任务方便,不过也可以接受,只需要简单的配置就可以使用了。

     

    展开全文
  • ​​​​​​​核心思想:FCFS算法是指进程调度时是从就绪的进程队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行的一种调度算法。 作用对象:既可用于作业调度,又可以用于进程调度。 缺点 不...
  • Hadoop 三大调度策略 三种调度

    千次阅读 2019-09-05 20:27:55
    种调度器简介 yarn常见的有三种调度器 他们分别是容器调度(Capacity Scheduler)、公平调度器(Fair Scheduler)、先进先出调度器(FIFOScheduler)。 三个调度器的示例图 三个调度器的区别 FIFO Scheduler FIFO ...
  • Hadoop YARN同时支持内存和CPU两种资源的调度(默认只支持内存,如果想进一步调度CPU,需要自己进行一些配置),本文将介绍YARN是如何对这些资源进行调度和隔离的。 在YARN中,资源管理由ResourceManager和...
  • request.getRequestDispatcher()调度跳转两种方法

    万次阅读 多人点赞 2019-03-17 17:36:36
    request.getRequestDispatcher()有两种跳转: (1)跳转到一个servlet request.getRequestDispatcher("想跳转的servlet名").forward(request, response); (2)跳转到一个页面 request....
  • 调度机制

    千次阅读 2021-02-14 09:55:37
    主要有两种调度模型:分时调度模型和抢占式调度模型 基于时间片轮转法的抢占式调度。线程调度器会给高优先级有更多的运行机会,如果优先级相同则随机选中,执行时长到达时间片后从新进行调度 线程的调度不是跨...
  • 它综合了经典流水车间和并行机两种调度的特点。 如下图所示,从开始到结束有m个加工阶段,每个加工阶段内有不同数量的并行机,需要加工的工件从开始一次经过每个加工阶段,在每个加工阶段中可以被该阶段内的任意一...
  • 为什么需要集群管理与调度上文我们简单介绍了深度学习、分布式CPU+GPU集群的实现原理,以及分布式深度学习的原理,我们简单回顾一下:分布式CPU+GPU集群的实现:GPU集群并行模式即为多GPU并行中各种并行模式的扩展,...
  • 常见的调度算法

    万次阅读 多人点赞 2018-11-18 16:58:34
    一、处理机调度相关基本概念 1、调度方式和调度算法的若干准则 1)面向用户的准则:周转时间短(CPU执行用时Ts、周转时间T=Ts+Tw、带权周转时间W= T/Ts)、响应时间快、均衡性、截止时间的保证、优先权准则 2)面向...
  • Yarn三种调度策略对比

    千次阅读 2018-11-01 09:20:00
      理想情况下,我们应用对Yarn资源的请求应该立刻得到满足,但现实情况资源往往是有限的,特别是在一个很繁忙的集群,一个应用资源的请求经常需要等待一段时间才能的到相应...  在Yarn中有三种调度器可以选择:F...
  • 计算机通常只有一个CPU,在任意时刻只能执行一条机器指令,每个线程只有获得CPU的使用权才能执行指令.所谓多线程的并发运行,其实是指从宏观上看,各个线程轮流获得CPU的... 有两种调度模型:分时调度模型和抢占式调度模
  • CPU调度策略

    千次阅读 2019-07-27 14:41:23
    CPU调度 我们知道,程序需要获得CPU的资源才能被调度和执行,那么当一个进程由于某种原因放弃CPU然后进入阻塞状态,下一个获得CPU资源去被调度执行的进程会是谁呢?下图中,进程1因为阻塞放弃CPU资源,此时,进程2...
  • 公平调度和容量调度的区别

    千次阅读 2013-12-18 09:05:18
    公平调度是以pool为单位分配任务slots的,容量调度以queue的方式分配tasktracker的,当都只有一个job的时候,两种调度器都可以利用整个集群的资源,在每个pool内部可以是以FIFO方式调度也可以是公平方式调度,但是在...
  • 台机器上加工的时间分别为ai 和bi 。 确定这n个作业的加工顺序,使得从第一台作业开始加工,到最后一个作业完成加工所需要的时间最少。 递归关系:T(S, t) = min{ ai + T(S - {i}, bi) } 1 &lt;= i...
  • 该项目在Linux内核中实现了基于IP的数据请求负载均衡调度方案,其体系结构如图1所示,终端互联网用户从外部访问公司的外部负载均衡服务器,终端用户的Web请求会发送给LVS调度器,调度器根据自己预设的算法决定将该...
  • nginx四种调度算法、进阶

    千次阅读 2017-11-06 13:08:44
    upstream 支持4负载均衡调度算法:A)轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器;B)ip_hash:每个请求按访问IP的hash结果分配,同一个IP客户端固定访问一个后端服务器;C)url_hash:按访问url的hash结果...
  • LVS十种调度算法介绍

    千次阅读 2015-03-14 22:25:07
    转自:12 1.轮叫调度(Round Robin)(简称rr)  轮叫调度(Round Robin ...算法的优点是其简洁性,它无需记录当前所有连接的状态,不管服务器上实际的连接数和系统负载,所以它是一无状态调度。 2.加权轮叫(Wei
  • Spark 的调度策略

    千次阅读 2015-09-16 22:39:28
    Spark的调度策略Spark目前有两种调度策略,一种是FIFO即先来先得,另一种是FAIR即公平策略。所谓的调度策略就是对待调度的对象进行排序,按照优先级来进行调度。调度的排序接口如下所示,就是对两个可调度的对象进行...
  • Linux进程调度(4):实时调度

    千次阅读 2012-03-20 22:36:26
    两种调度算法实现的都是静态优先级。内核不为实时进程计算动态优先级。这能保证给定优先级别的实时进程总能抢占优先级比他低得进程。linux的实时调度算法提供了一种软实时工作方式。实时优先级范围从0到MAX_RT_...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 422,423
精华内容 168,969
关键字:

两种调度