zoukankan      html  css  js  c++  java
  • java----高级多线程

    任务定时调度

    简单任务调度(Timer类)

        public static void main(String[] args) {
            Timer timer = new Timer();
            //1秒后执行run(),只执行一次
    //        timer.schedule(new TimerTask() {
    //            @Override
    //            public void run() {
    //                System.out.println("test");
    //            }
    //        },1000);
    
            //1秒之后每隔一秒执行run()方法
    //        timer.schedule(new TimerTask() {
    //            @Override
    //            public void run() {
    //                System.out.println("test");
    //            }
    //        },1000,1000);
    
            GregorianCalendar gregorianCalendar = new GregorianCalendar(2019, 9, 1, 19, 20,00);
            //Tue Oct 01 19:20:00 CST 2019 注意0是1月
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    System.out.println("test");
                }
            }, gregorianCalendar.getTime(),1000);
        }

    复杂的任务调度

    quartz框架(已经集成到spring中了)

    如果需要系统学习这个框架,需要将这个框架下载下来,里面example中有使用案例;

    使用maven下载依赖

    <!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.3.1</version>
    </dependency>
    

    基本使用

    实际过程中直接使用,不需要写,example中有使用案例。

    public class Demo {
        public static void main(String[] args) {
            //创建Scheduler工厂
            StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
            //从工厂获得调度器
            try {
                Scheduler scheduler = stdSchedulerFactory.getScheduler();
                //设置时间规则
                Date date = DateBuilder.evenSecondDateAfterNow();
                //设置执行的工作
                JobDetail jobDetail= JobBuilder.newJob(Test.class).withIdentity("test").build();
                //设置触发条件
                Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger").startAt(date).build();
                //注册任务和条件
                scheduler.scheduleJob(jobDetail,trigger);
                scheduler.start();
                //scheduler.shutdown();
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
    
        }
    }

    必须是一个public类

    public class Test implements Job {
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            System.out.println("started");
        }
    }
    

    补充

    //每隔2秒执行一次,重复3次(一共会重复4次)
    Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger").startAt(date).withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).withRepeatCount(3)).build();

    HappenBefore

    你写的代码很可能根本没按你期望的顺序执行,因为编译器和CPU会尝试重排指令使得代码更快地运行,称为指令重排。

    前提是数据之前没有依赖,可能后面的代码会先执行

    首先自己写的代码会被编译成机器指令(其中的变量会被决定有那个寄存器存储)

    从内存中获取一条指令。从对应的寄存器中获取相应的数据值(copy一份到工作内存),cpu计算结果,同步到主存中(这一步可能会出现问题,原因同步比较慢

    同步数据慢:造成数据不一致

    数据之间没有依赖:操作指令重排

    public class Demo {
        private static int a=0;
        private static Boolean flag=false;
        public static void main(String[] args) {
            //如果没有出错,可以将循环次数加大
            for (int i = 0; i < 100; i++) {
                a = 0;
                flag = false;
                Thread t1 = new Thread(() -> {
                    a = 1;
                    flag = true;
                });
                Thread t2 = new Thread(() -> {
                    if (flag){
                        a*=1;
                    }
                    //按照预期值a是不可能是0的
                    if (a==0){
                        System.out.println("happed before-->a="+a);
                    }
                });
                t1.start();
                t2.start();
                try {
                    t1.join();
                    t2.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    ThreadLocal

    即使定义在成员变量中,所有的线程对他的操作相互不影响,都把他当做了局部变量。

    public class Demo {
        private volatile static int i = 0;
        private static ThreadLocal threadLocal1 = new ThreadLocal<Integer>();
        private static ThreadLocal threadLocal2 = new ThreadLocal<Integer>(){
            @Override
            protected Integer initialValue() {
                return 0;
            }
        };
    
        public static void main(String[] args) throws InterruptedException {
            //默认初始化为null;
            System.out.println(threadLocal1.get());
            //重写initialValue方法,赋给初始值.
            System.out.println(threadLocal2.get());
            new Thread(()->{
                threadLocal1.set(11);
                System.out.println(threadLocal1.get());
            }).start();
            new Thread(()->{
                System.out.println(threadLocal1.get());
            }).start();
        }
    }
    

    InheritableThreadLocal

    和ThreadLocal用法一样,只是子线程会继承父线程的数据,但是子线程修改数据不会影响父线程,一旦子线程修改了了数据,父线程在修改数据就不会影响子线程了。

  • 相关阅读:
    docker for zabbix
    由阿里云宕机引发的思考
    linux清空文件
    RDS导入注意事项
    coreos 常见问题
    2018年7月28日笔记
    2018年7月26日笔记
    2018年7月24日笔记
    作业五之系统设计时所实现的质量属性战术
    作业四之阅读《大型网站技术架构:核心原理与案例分析》第五、六、七章
  • 原文地址:https://www.cnblogs.com/yanxiaoge/p/11615811.html
Copyright © 2011-2022 走看看