Timer
Timer计时器具备使任务延迟执行以及周期性执行的功能,但是Timer天生存在一些缺陷,所以从JDK 1.5开始就推荐使用ScheduledThreadPoolExecutor(ScheduledExecutorService实现类)作为其替代工具。
首先Timer对提交的任务调度是基于绝对时间而不是相对时间的,所以通过其提交的任务对系统时钟的改变是敏感的(譬如提交延迟任务后修改了系统时间会影响其执行);而ScheduledThreadExecutor只支持相对时间,对系统时间不敏感。
接着Timer的另一个问题是如果TimerTask抛出未检查异常则Timer将会产生无法预料的行为,因为Timer线程并不捕获异常,所以TimerTask抛出的未检查异常会使Timer线程终止,所以后续提交的任务得不到执行;而ScheduledThreadPoolExecutor不存在此问题。
所有的现代操作系统都通过进程和线程来支持并发。进程是通常彼此独立运行的程序的实例,比如,如果你启动了一个Java程序,操作系统产生一个新的进程,与其他程序一起并行执行。在这些进程的内部,我们使用线程并发执行代码,因此,我们可以最大限度的利用CPU可用的核心(core)。Java从JDK1.0开始执行线程。在开始一个新的线程之前,你必须指定由这个线程执行的代码,通常称为task。这可以通过实现Runnable——一个定义了一个无返回值无参数的run()方法的函数接口,如下面的代码所示:
Runnable task = () -> {
String threadName = Thread.currentThread().getName();
System.out.println("Hello " + threadName);
};
task.run();
Thread thread = new Thread(task);
thread.start();
System.out.println("Done!");
因为Runnable是一个函数接口,所以我们利用lambda表达式将当前的线程名打印到控制台。首先,在开始一个线程前我们在主线程中直接运行runnable。控制台输出的结果可能像下面这样:
Hello main
Hello Thread-0
Done!
或者这样:
Hello main
Done!
Hello Thread-0