(五) 多线程应用

Timer方法API

Timer类主要负责计划任务的功能,也就是在指定的时间开始执行某一个任务。Timer类的主要作用就是设置计划任务,但封装任务的类却是 TimerTask类。执行计划任务的代码要放入 TimerTask的子类中(TimerTask类是实现Runnable接口的抽象类) 。

1. schedule(TimerTask task,Date date)

作用:在指定的日期执行一次某方法

public class TimerI extends TimerTask {
    @Override
    public void run() {
        System.out.println("Timer定时执行!");
    }
}

public class RunMain {
    public static void main(String[] args) {
        Timer timer = new Timer();
        String runTime = "2019-03-01 15:42:00";
        Date date = DateUtil.parse(runTime, DatePattern.NORM_DATETIME_PATTERN);
        TimerI timerI = new TimerI();
        timer.schedule(timerI, date);
    }
}

TimerTask是以队列的方式按顺序执行的,执行的时间有可能和预期的不一致,因为前面的任务有可能消耗的时间较长,则后面的任务运行的时间也会被延迟。

2. schedule( TimerTask task, Date time, long period)

作用:在指定的日期开始,按指定的间隔周期性地无限循环地执行某一任务。

3. cancel()

TimerTask类中的 cancel方法的作用是将自身从任务队列中清除(其他任务没影响)

public class TimerI extends TimerTask {
    @Override
    public void run() {
        System.out.println("TimerI 定时执行!");
        this.cancel();
    }
}

public class TimerII extends TimerTask {
    @Override
    public void run() {
        System.out.println("TimerII 定时执行!");
    }
}

public class RunMain {
    public static void main(String[] args) {
        Timer timer = new Timer();
        String runTime = "2019-03-01 16:24:00";
        Date date = DateUtil.parse(runTime, DatePattern.NORM_DATETIME_PATTERN);
        TimerI timerI = new TimerI();
        TimerII timerII = new TimerII();
        timer.schedule(timerI, date,22);
        timer.schedule(timerII,date,30);
    }
}

运行结果:
在这里插入图片描述
Timer类中的 cancel() 方法的作用是将任务队列中的全部任务清空

4. schedule( TimerTask task, long delay)

作用:以当前的时间为参考,延迟指定的毫秒数后执行一次 TimerTask任务。

5. schedule( TimerTask task, long delay, long period)

作用:以当前的时间为参考,延迟指定的毫秒数,以某一间隔时间无限次数地执行某一任务。

6. scheduleAtFixedRate(Timer Task task, Date time, long period)

schedule和 scheduleAtFixed Rate主要的区别:

① 使用 schedule方法:如果执行任务的时间没有被延时,那么下一次任务的执行时间参考上一次任务的“开始”时的时间来计算
使用 scheduleAtFixedRate方法:如果执行任务的时间没有被延时,那么下一次任务的执行时间参考上一次任务的“结束”时的时间来计算。
② schedule方法不具有追赶执行性(即 计划时间早于当前时间时,只从当前时间开始执行),scheduleAtFⅸedRate方法具有追赶执行性(即 计划时间早于当前时间时,从计划时间补充性的开始执行)
在这里插入图片描述

单例模式

在多线程环境中,使用懒汉模式的单例模式会出现非线程安全问题

public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {
    }

    public static LazySingleton getInstance() throws InterruptedException {
        if (instance != null) {
            Thread.sleep(100);
            instance = new LazySingleton();
        }
        return instance;
    }
}

运行结果:
在这里插入图片描述
由结果可知多线程环境中,懒汉单例模式获取到的单例对象是线程不安全的!
解决办法:

① 使用synchronized同步方法获取实例对象,但同步方法运行效率比较低
② 双检查锁机制
在这里插入图片描述

SimpleDateFormat

SimpleDateFormat类主要负责日期的转换与格式化,但在多线程的环境中容易造成数据转换及处理的不准确。

public class ThreadIII extends Thread {

    private SimpleDateFormat simple;

    private String dateString;

    public ThreadIII(SimpleDateFormat simple, String dateString) {
        this.simple = simple;
        this.dateString = dateString;
    }

    @Override
    public void run() {
        try {
            Date date = simple.parse(dateString);
            String newDate = simple.format(date).toString();
            System.out.println("正确日期:" + dateString+"   输出时间:" + newDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

public class RunMain {
    public static void main(String[] args) {
        SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd");
        String[] dateArray = new String[]{"2019-01-22", "2018-11-12", "2019-02-02", "2018-12-22"};
        ThreadIII[] threadIIIS = new ThreadIII[dateArray.length];
        for (int i = 0; i < dateArray.length; i++) {
            threadIIIS[i] = new ThreadIII(simple, dateArray[i]);
            threadIIIS[i].start();
        }
    }
}

运行结果:
在这里插入图片描述
明显,运行结果数据异常!建议使用 DateTimeFormatter

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值