- 因为前面连个之前已经讲过了,所以这里主要强调的是第三种方式创建线程
- Callable接口时JDK1.8之后新设置的一个接口,主要作用是在重写 call() 方法的时候可以返回参数
- package Timer_;
-
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.FutureTask;
-
- public class Timer_ {
- public static void main(String[] args) {
- // 使用匿名内部类, FutureTask相当于Thread 的作用,new 出来的对象,没有start方法,
- // 还是要通过new Thread 对象调用start方法来启动线程
- FutureTask
ft = new FutureTask<>(new Callable() { - @Override
- public String call() throws Exception {
- Thread.sleep(1000 * 2);
- System.out.println("MyCall线程开始运行...");
- return "返回值!";
- }
- });
-
- Thread td = new Thread(ft);
- td.start();
-
- String result = null;
- try {
- result = ft.get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- System.out.println("main线程得到了"+result);
- System.out.println("main线程结束了...");
-
- }
- }
-
运行结果:
MyCall线程开始运行...
main线程得到了我是返回值!main线程结束了...
1.1 基本实现步骤:
- 第一步: FutureTask ft = new FutureTask(new Callable(){ @Override public String call() throws Exception {//run() 自动被调用 System.out.println("MyCall线程开始"); Thread.sleep(1000 * 10); return "返回值!"; } });
- 第二步: Thread ta = new Thread(ft);
- 第三步: ta.start();// 执行call()
- 第四步:Object Object o = ft.get();//处理异常,导致当前线程阻塞,继续执行当前线程
- 第五步: 获取结果处理结果
- 用户线程: 执行任务,任务完成之后关闭
- 守护线程: 之哟啊有一个用户线程在运行,守护线程就一直运行,比如: GC垃圾回收器
- 守护线程的用法: 线程对象. setDaemon(true);
- new Timer (true) :守护(守护线程)始终
- new Timer () 非守护线程
- public void schedule ( TimerTask task, Date firstTime, long period)
- 第一个task ,要执行的任务(打印系统日志),Date firstTime:第一次开始日期,long period :周期
- public abstract class TimerTask 可以传入线程对象的构造方法中
- TimerTsk extends Object implements Runnable
- public abstract void run ();
3.1 具体用法-案例
- package Timer_;
-
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.Timer;
- import java.util.TimerTask;
-
- public class Timers_ {
- public static void main(String[] args) {
-
- Timer timer = new Timer(true); // 创建守护时钟
- Mytask mytask = new Mytask();
-
- Date time =null;
- SimpleDateFormat spf = new SimpleDateFormat("yyyy年 MM月 dd日 HH时:mm分:ss秒");
- try {
- time = spf.parse("2022年 08月 10日 22时:05分:50秒");
- } catch (ParseException e) {
- e.printStackTrace();
- }
-
- timer.schedule(mytask,time,1000*5);
-
- for (int i = 0; i < 30; i++) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("mian线程执行到"+i);
- }
- System.out.println("main线程执行结束...");
- }
- }
-
- class Mytask extends TimerTask {
- @Override
- public void run() {
- String name = Thread.currentThread().getName();
- // HH 是24小时进制,月份MM必须大写
- SimpleDateFormat spf = new SimpleDateFormat("yyyy年 MM月 dd日 HH时:mm分:ss秒");
- String time = spf.format(new Date());
- System.out.println(name+"--->"+time);
- }
- }
-
运行结果:
例题总结:
- 这是一个非常有意思的例题,首先考察的是对时间Date类的运行,一定要非常的熟练才行
- 考察对线程的应用,守护始终就是一个扩张,通过运行结果图,我们可以很清楚的看到程序已经实现 了预期效果
- 如果将守护始终配合IO流进行扩展,那么不久可以打印出我们想要的程序运行日志了嘛!还是非常有意思的
- 最后留一个小点,这里Mytask类,非常显眼,可以直接schedule方法中写成匿名内部类,这样看上去更加简洁一些,匿名内部类可以写接口,也可以写抽象方法!!