【慕课笔记】Java定时任务调度工具详解之Timer篇_0理论

慕课地址

1 简单介绍

1)什么是定时任务调度
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2)Timer简介
打开jdk-zh说明文档查看即可
在这里插入图片描述
推荐看英文版本的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
简单写个demo,感受一下timer的定时调度函数.schedule()(本人实践用的是idea,也可以用eclipse等,看个人喜好)
在这里插入图片描述
MyTimerTask.java

package com.java.study.timer;
import java.util.TimerTask;

public class MyTimerTask extends TimerTask {
    private String name;
    public MyTimerTask(String inputname) {
        name = inputname;
    }

    @Override
    public void run() {
        System.out.println("Current name is " + name);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

MyTimer.java

package com.java.study.timer;

import java.util.Timer;

public class MyTimer {
    public static void main(String[] args) {
        // 1. 创建一个Timer实例
        Timer timer = new Timer();
        // 2. 创建一个MyTimerTask实例
        String inputname = "hello timer";
        MyTimerTask myTimerTask = new MyTimerTask(inputname);
        // 3. 通过timer定时定频率调用myTimerTask的业务逻辑
        // 定时即当前执行时间的2s之后;
        // 定频率即之后每隔1s执行一次;
        timer.schedule(myTimerTask, 2000L, 1000L);
    }
}

执行效果:
在这里插入图片描述
3)基于上面的实践,来说说Timer的定时调度函数
在这里插入图片描述
schedule的四种用法:
在这里插入图片描述
在这里插入图片描述
实际操作一下试试看:
MyTimerTask.java

...
    @Override
    public void run() {
        // 实现自己的业务逻辑 todo
        // 以yyyy-MM-dd HH:mm:ss的格式打印当前执行时间
        // 如:2020-04-06 12:12:12
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Current time is " + simpleDateFormat.format(calendar.getTime()));
        // 此处是demo只增加一个打印输出语句
        System.out.println("Current name is " + name);
    }
   ...
}

MyTimer.java

...
public class MyTimer {
    public static void main(String[] args) {
		...
        /**
         * 获取当前时间,并设置成距离当前时间3秒之后的时间
         * 如:当前是2020-04-06 12:12:12
         * 则设置后的时间则为2020-04-06 12:12:15
         */
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Real Current time is " + simpleDateFormat.format(calendar.getTime()));
        // 当前时间被设置成距离当前时间3秒之后的时间
        calendar.add(Calendar.SECOND, 3);

        // ----------- schedule 的用法 -----------
        /**
         * 1、在时间等于或超过time的时候执行,且只执行一次task
         * 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
         */
        myTimerTask.setName("schedule_1 ======== ");
        timer.schedule(myTimerTask, calendar.getTime());
    }
}

实际效果:
在这里插入图片描述
在这里插入图片描述
实际操作一下试试看:
MyTimer.java

// ----------- schedule 的用法 -----------
        /**
         * 1、在时间等于或超过time的时候执行,且只执行一次task
         * 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
         */
//        myTimerTask.setName("schedule_1 ======== ");
//        timer.schedule(myTimerTask, calendar.getTime());

        /**
         * 2、在时间等于或超过time的时候首次执行task
         *    之后每隔period毫秒重复执行一次task
         * 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
        myTimerTask.setName("schedule 2 ========");
        timer.schedule(myTimerTask, calendar.getTime(), 2000);

实际效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述实际操作一下试试看:
MyTimer.java

// ----------- schedule 的用法 -----------
        /**
         * 1、在时间等于或超过time的时候执行,且只执行一次task
         * 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
         */
//        myTimerTask.setName("schedule_1 ======== ");
//        timer.schedule(myTimerTask, calendar.getTime());

        /**
         * 2、在时间等于或超过time的时候首次执行task
         *    之后每隔period毫秒重复执行一次task
         * 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
//        myTimerTask.setName("schedule 2 ========");
//        timer.schedule(myTimerTask, calendar.getTime(), 2000);

        /**
         * 3、等待delay毫秒后执行且只执行一次task
         * 如:现在是2020-04-06 12:12:15,delay=1000
         *     那么会在2020-04-06 12:12:16 执行一次task--打印时间的任务
         */
        myTimerTask.setName("schedule 3 ========");
        timer.schedule(myTimerTask, 1000);

实际效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
实际操作一下试试看:
MyTimer.java

// ----------- schedule 的用法 -----------
        /**
         * 1、在时间等于或超过time的时候执行,且只执行一次task
         * 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
         */
//        myTimerTask.setName("schedule_1 ======== ");
//        timer.schedule(myTimerTask, calendar.getTime());

        /**
         * 2、在时间等于或超过time的时候首次执行task
         *    之后每隔period毫秒重复执行一次task
         * 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
//        myTimerTask.setName("schedule 2 ========");
//        timer.schedule(myTimerTask, calendar.getTime(), 2000);

        /**
         * 3、等待delay毫秒后执行且只执行一次task
         * 如:现在是2020-04-06 12:12:15,delay=1000
         *     那么会在2020-04-06 12:12:16 执行一次task--打印时间的任务
         */
//        myTimerTask.setName("schedule 3 ========");
//        timer.schedule(myTimerTask, 1000);

        /**
         * 4、等待delay毫秒首次执行task     和2类似
         *    之后每隔period毫秒重复执行一次task
         * 如:现在是2020-04-06 12:12:15,delay=1000 ms
         *     那么会在2020-04-06 12:12:16 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
        myTimerTask.setName("schedule 4 ========");
        timer.schedule(myTimerTask,1000, 2000);

实际效果:
在这里插入图片描述
scheduleAtFixedRate的两种用法:
在这里插入图片描述
在这里插入图片描述
实际操作一下试试看:
MyTimer.java

// ----------- schedule 的用法 -----------
        /**
         * 1、在时间等于或超过time的时候执行,且只执行一次task
         * 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
         */
//        myTimerTask.setName("schedule_1 ======== ");
//        timer.schedule(myTimerTask, calendar.getTime());

        /**
         * 2、在时间等于或超过time的时候首次执行task
         *    之后每隔period毫秒重复执行一次task
         * 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
//        myTimerTask.setName("schedule 2 ========");
//        timer.schedule(myTimerTask, calendar.getTime(), 2000);

        /**
         * 3、等待delay毫秒后执行且只执行一次task
         * 如:现在是2020-04-06 12:12:15,delay=1000
         *     那么会在2020-04-06 12:12:16 执行一次task--打印时间的任务
         */
//        myTimerTask.setName("schedule 3 ========");
//        timer.schedule(myTimerTask, 1000);

        /**
         * 4、等待delay毫秒首次执行task     和2类似
         *    之后每隔period毫秒重复执行一次task
         * 如:现在是2020-04-06 12:12:15,delay=1000 ms
         *     那么会在2020-04-06 12:12:16 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
//        myTimerTask.setName("schedule 4 ========");
//        timer.schedule(myTimerTask,1000, 2000);

        // ----------- scheduleAtFixedRate 的用法 -----------
        /**
         * 1、在时间等于或超过time的时候首次执行task     基本和schedule的用法 2一样
         *    之后每隔period毫秒重复执行一次task
         * 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
        myTimerTask.setName("scheduleAtFixedRate 1 ========");
        timer.scheduleAtFixedRate(myTimerTask, calendar.getTime(), 2000);

实际效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
实际操作一下试试看:
MyTimer.java

// ----------- schedule 的用法 -----------
        /**
         * 1、在时间等于或超过time的时候执行,且只执行一次task
         * 如:在2020-04-06 12:12:15执行一次task--打印时间的任务
         */
//        myTimerTask.setName("schedule_1 ======== ");
//        timer.schedule(myTimerTask, calendar.getTime());

        /**
         * 2、在时间等于或超过time的时候首次执行task
         *    之后每隔period毫秒重复执行一次task
         * 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
//        myTimerTask.setName("schedule 2 ========");
//        timer.schedule(myTimerTask, calendar.getTime(), 2000);

        /**
         * 3、等待delay毫秒后执行且只执行一次task
         * 如:现在是2020-04-06 12:12:15,delay=1000
         *     那么会在2020-04-06 12:12:16 执行一次task--打印时间的任务
         */
//        myTimerTask.setName("schedule 3 ========");
//        timer.schedule(myTimerTask, 1000);

        /**
         * 4、等待delay毫秒首次执行task     和2类似
         *    之后每隔period毫秒重复执行一次task
         * 如:现在是2020-04-06 12:12:15,delay=1000 ms
         *     那么会在2020-04-06 12:12:16 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
//        myTimerTask.setName("schedule 4 ========");
//        timer.schedule(myTimerTask,1000, 2000);

        // ----------- scheduleAtFixedRate 的用法 -----------
        /**
         * 1、在时间等于或超过time的时候首次执行task     基本和schedule的用法 2一样
         *    之后每隔period毫秒重复执行一次task
         * 如:在2020-04-06 12:12:15 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
//        myTimerTask.setName("scheduleAtFixedRate 1 ========");
//        timer.scheduleAtFixedRate(myTimerTask, calendar.getTime(), 2000);

        /**
         * 2、等待delay毫秒首次执行task      基本和schedule的用法 4一样
         *    之后每隔period毫秒重复执行一次task
         * 如:现在是2020-04-06 12:12:15,delay=1000 ms
         *     那么会在2020-04-06 12:12:16 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
        myTimerTask.setName("scheduleAtFixedRate 2 ========");
        timer.scheduleAtFixedRate(myTimerTask,1000, 2000);

实际效果:
在这里插入图片描述
以上两者的区别呢?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ScheduleAndScheduleAtFixedRateDifferenceTest.java

package com.java.study.timer;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class ScheduleAndScheduleAtFixedRateDifferenceTest {
    public static void main(String[] args) {
        // 规定时间格式
        final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 获取当前时间 具体到时分秒
        Calendar calendar = Calendar.getInstance();
        System.out.println("Current time is "
                + sf.format(calendar.getTime()));
        // 把当前时间设置成6秒之前的时间
        // 如:当前时间为 2020-04-07 12:00:06,
        //     那么设置之后的时间为 2020-04-07 12:00:00
        calendar.add(Calendar.SECOND, -6);
        System.out.println("after -6s Current time is "
                + sf.format(calendar.getTime()));

        Timer timer = new Timer();
        // 第一次执行前是6秒前,之后每隔两秒执行一次
        // 下面为了方便直接定义一个内部TimerTask类,然后简单写一些业务逻辑
        // 1、看看schedule 的表现
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("schedule exec time is "
                        + sf.format(scheduledExecutionTime()));
            }
        }, calendar.getTime(), 2000);
        // 2、看看scheduleAtFixedRate 的表现
		// todo
    }
}

实际效果:
可以看到任务的执行不会因为当前时间被修改为6秒之前,就按照6秒之前的时间来执行,而是按照当前实际的时间来执行,然后每隔两秒执行一次。这就是schedule的特点。
在这里插入图片描述
在这里插入图片描述
ScheduleAndScheduleAtFixedRateDifferenceTest.java

package com.java.study.timer;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class ScheduleAndScheduleAtFixedRateDifferenceTest {
    public static void main(String[] args) {
        // 规定时间格式
        final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 获取当前时间 具体到时分秒
        Calendar calendar = Calendar.getInstance();
        System.out.println("Current time is "
                + sf.format(calendar.getTime()));
        // 把当前时间设置成6秒之前的时间
        // 如:当前时间为 2020-04-07 12:00:06,
        //     那么设置之后的时间为 2020-04-07 12:00:00
        calendar.add(Calendar.SECOND, -6);
        System.out.println("after -6s Current time is "
                + sf.format(calendar.getTime()));

        Timer timer = new Timer();
        // 第一次执行前是6秒前,之后每隔两秒执行一次
        // 下面为了方便直接定义一个内部TimerTask类,然后简单写一些业务逻辑
        // 1、看看schedule 的表现
//        timer.schedule(new TimerTask() {
//            @Override
//            public void run() {
//                System.out.println("schedule exec time is "
//                        + sf.format(scheduledExecutionTime()));
//            }
//        }, calendar.getTime(), 2000);
        // 2、看看scheduleAtFixedRate 的表现
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println("schedule exec time is "
                        + sf.format(scheduledExecutionTime()));
            }
        }, calendar.getTime(), 2000);

    }
}

实际效果:
可以看到当前时间是52,但是计划执行时间是从6秒前开始算的,实际上下图红框中的4次schedule exec time是52秒这个时间点并发执行了3次(即“追赶”)才追上52这个时间点,之后才是真正的每隔2秒执行一次。
在这里插入图片描述
在这里插入图片描述
ScheduleAndScheduleAtFixedRateDifferenceTest2.java

package com.java.study.timer;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class ScheduleAndScheduleAtFixedRateDifferenceTest2 {
    public static void main(String[] args) {
        // 规定时间格式
        final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 获取当前时间 具体到时分秒
        Calendar calendar = Calendar.getInstance();
        System.out.println("Current time is "
                + sf.format(calendar.getTime()));

        Timer timer = new Timer();
        // 第一次执行当前时间,之后计划是每隔2秒执行一次,但是timertask任务每次实际执行时间是3秒,所以以后每次执行都是间隔3秒
        // 下面为了方便直接定义一个内部TimerTask类,然后简单写一些业务逻辑
        // 1、看看 schedule 的表现
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                // try 防止出现异常问题
                try {
                    Thread.sleep(3000);   // 这里强制让timertask任务执行时间3秒,超过设定的间隔时间2秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 打印最近一次的计划时间
                System.out.println("schedule exec time is "
                        + sf.format(scheduledExecutionTime()));
            }
        }, calendar.getTime(), 2000);
        // 2、看看 scheduleAtFixedRate 的表现
    }
}

实际效果:
可以看到执行间隔是3秒,而不是2秒了。
在这里插入图片描述
在这里插入图片描述
ScheduleAndScheduleAtFixedRateDifferenceTest2.java

package com.java.study.timer;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class ScheduleAndScheduleAtFixedRateDifferenceTest2 {
    public static void main(String[] args) {
        // 规定时间格式
        final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 获取当前时间 具体到时分秒
        Calendar calendar = Calendar.getInstance();
        System.out.println("Current time is "
                + sf.format(calendar.getTime()));

        Timer timer = new Timer();
        // 第一次执行当前时间,之后计划是每隔2秒执行一次,但是timertask任务每次实际执行时间是3秒,所以以后每次执行都是间隔3秒
        // 下面为了方便直接定义一个内部TimerTask类,然后简单写一些业务逻辑
        // 1、看看 schedule 的表现
//        timer.schedule(new TimerTask() {
//            @Override
//            public void run() {
//                // try 防止出现异常问题
//                try {
//                    Thread.sleep(3000); // 这里强制让timertask任务执行时间3秒,超过设定的间隔时间2秒
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                // 打印最近一次的计划时间
//                System.out.println("schedule exec time is "
//                        + sf.format(scheduledExecutionTime()));
//            }
//        }, calendar.getTime(), 2000);
        // 2、看看 scheduleAtFixedRate 的表现
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                // try 防止出现异常问题
                try {
                    Thread.sleep(3000); // 这里强制让timertask任务执行时间3秒,超过设定的间隔时间2秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 打印最近一次的计划时间
                System.out.println("schedule exec time is "
                        + sf.format(scheduledExecutionTime()));
            }
        }, calendar.getTime(), 2000);

    }
}

实际效果:
可以看到执行间隔还是2秒,而不是3秒。
在这里插入图片描述

4)其他重要函数
在这里插入图片描述
TimerTask的cancel()方法
在这里插入图片描述
实际操作一下试试看:
MyTimerTask.java

public class MyTimerTask extends TimerTask {
	...
    private Integer count = 0;
	...
    @Override
    public void run() {
        // 实现自己的业务逻辑 todo
        if (count < 3) {
            // 以yyyy-MM-dd HH:mm:ss的格式打印当前执行时间
            // 如:2020-04-06 12:12:12
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Current time is " + simpleDateFormat.format(calendar.getTime()));
            // 此处是demo只增加一个打印输出语句
            System.out.println("Current name is " + name);
            count++;
        } else {
            cancel();   // 执行任务超过3次就取消task,相当于跳出定时任务循环
            System.out.println("Cancel task done!");
        }
    }
    ...

实际效果:
在这里插入图片描述
TimerTask的scheduledExecutionTime()方法
在这里插入图片描述
在这里插入图片描述
实际操作一下试试看:
MyTimer.java

        /**
         * 2、等待delay毫秒首次执行task      基本和schedule的用法 4一样
         *    之后每隔period毫秒重复执行一次task
         * 如:现在是2020-04-06 12:12:15,delay=1000 ms
         *     那么会在2020-04-06 12:12:16 首次执行task--打印时间的任务
         *     之后每隔2秒(即2000ms)执行一次task
         */
//        myTimerTask.setName("scheduleAtFixedRate 2 ========");
//        timer.scheduleAtFixedRate(myTimerTask,1000, 2000);

        // scheduledExecutionTime() 用法
        // 最近发生此任务执行--安排的时间,为long型
        myTimerTask.setName("scheduledExecutionTime 1111 ========");
        timer.schedule(myTimerTask, 5000);
        System.out.println("schedule time which task will run is " + simpleDateFormat.format(myTimerTask.scheduledExecutionTime()));
    ...

实际效果:
在这里插入图片描述
Timer的cancel()方法
在这里插入图片描述
实际操作一下试试看:
TimerCancelTest.java

package com.java.study.timer;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;

public class TimerCancelTest {
    public static void main(String[] args) throws InterruptedException {
        // 1. 创建一个Timer实例
        Timer timer = new Timer();
        // 2. 创建一个MyTimerTask实例
        String inputname = "hello timer";
        String inputname_1 = "hello timer 1";
        MyTimerTask task1 = new MyTimerTask(inputname);
        MyTimerTask task2 = new MyTimerTask(inputname_1);

        // 获取当前时间
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Real Current time is " + simpleDateFormat.format(calendar.getTime()));

        // task1首次执行时距离当前时间3秒执行,之后每隔2s执行一次;
        // task2首次执行时距离当前时间1秒执行,之后每隔2s执行一次;
        timer.schedule(task1, 3000, 2000);
        timer.schedule(task2, 1000, 2000);

        // 休眠5秒
        Thread.sleep(5000);

        // 获取当前的时间并打印
        Date cancelTime = new Date();
        System.out.println("cancel time is " + simpleDateFormat.format(cancelTime));
        // 取消所有任务
        timer.cancel();
        System.out.println("All tasks be canceled!");

    }
}

实际效果:
在这里插入图片描述
Timer的purge()方法
在这里插入图片描述
在这里插入图片描述
实际操作一下试试看:
TimerCancelAndPurgeTest.java

package com.java.study.timer;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;

public class TimerCancelAndPurgeTest {
    public static void main(String[] args) throws InterruptedException {
        // 1. 创建一个Timer实例
        Timer timer = new Timer();
        // 2. 创建一个MyTimerTask实例
        String inputname = "hello timer";
        String inputname_1 = "hello timer 1";
        MyTimerTask task1 = new MyTimerTask(inputname);
        MyTimerTask task2 = new MyTimerTask(inputname_1);

        // 获取当前时间
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Real Current time is " + simpleDateFormat.format(calendar.getTime()));

        // task1首次执行时距离当前时间3秒执行,之后每隔2s执行一次;
        // task2首次执行时距离当前时间1秒执行,之后每隔2s执行一次;
        timer.schedule(task1, 3000, 2000);
        timer.schedule(task2, 1000, 2000);

        System.out.println("current canceled tasks num is " + timer.purge());
        // 休眠2秒
        Thread.sleep(2000);
        // 获取当前的时间并打印
        Date cancelTime = new Date();
        System.out.println("cancel time is " + simpleDateFormat.format(cancelTime));
        // 取消task2任务
        task2.cancel();
        System.out.println("current canceled tasks num is " + timer.purge());

    }
}


实际效果:
在这里插入图片描述
5)Timer的缺陷
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以上Timer的缺陷,用Quartz就可以完美解决。

todo:
Quartz相关。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值