两道笔试题的感触

今天做了两道笔试题,收益良多。
有些题,你会发现,虽然并不难,但是却很容易没有思路或者出错,这都是源自平时的不求甚解。
很多知识点,自以为已经掌握,其实只是管中窥豹,可见一斑。不要一味墨守成规,也要用于思考,很多东西既要知其然,
也要知其所以然。我一直觉得了解和精通中间差着十万八千里,看来还有很长一段路要走。
只有比别人更早、更勤奋地努力,才能尝到更加成功的滋味。哈哈,跑题了。

下面看一下两道笔试题。
一、大概简单地说一下,求下面这段代码的结果。

new Thread(new Runnable() {
            public void run() {
                System.out.println("runnable");
            }
        }){
            public void run() {
                System.out.println("thread");
            }
        }.start();


这题并不难,但是却易错。有人觉得输出runnable,有人觉得都应该输出,但其实输出的是thread。为什么呢?
之前,我们都知道创建线程有两种方式,1.继承Thread,重写run()方法;2.实现Runnable接口。但又没有人想过,
为什么有两种方法,哪种更好呢?
其实,一直以来,我都是用第二种比较多,看别人的代码也是第二种比较多。我个人觉得第二种更好一点,原因如下:
1.实现Runnable接口,可以让thread更具备灵活性。new Thread(runn),runn可以换成别的Runnable对象,这样一个Thread就具有了
多个行为。而第一种方法呢?new Thread(){ public void run(){...}},这样一个Thread对象就只有一种run行为了。
2.实现Runnable接口,可以更加体现面向对象的思想。面向对象,继承封装多态,我们习惯将一类东西封装成一个类,而这里Thread是
一个类,就是线程类,Runnable接口就是实现run()的动作,彼此分开。
下面分析这道题,我们可以看一下Thread源码:
 /* What will be run. */
    private Runnable target;
  @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
Runnable是它的一个属性,run()是它的一个方法,而这里我们用匿名内部类,实质就是Thread的子类对象重写了run()方法,
根据面向对象多态的知识,不难发现结果了吧。

二、利用Timer类,实现一种简单效果,2秒打印一次“boom”,再4秒打印一次,再两秒,再4秒……一直循环下去。(这道题可以扩展,
比如每天七点打印,每周的工作日八点打印等等,可以思考)

Timer类的嵌套使用,直接给出两种解决办法吧。

1.

public class Demo2 {
    public static void main(String[] args) {

        new Timer().schedule(new MyTimerTask(), 2000);
        while (true) {
            try {
                Thread.sleep(1000);
                System.out.println(new Date().getSeconds());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class MyTimerTask extends TimerTask {

    private static int count = 0;

    @Override
    public void run() {
        count = (count + 1) % 2;
        System.out.println("boom");
        new Timer().schedule(new MyTimerTask(), 2000 * (count + 1));
    }

}

2.

public class Demo3 {
    public static void main(String[] args) {
        new Timer().schedule(new MyTimerTask1(), 2000);
        
        while(true){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(new Date().getSeconds());
        }
    }
}

class MyTimerTask1 extends TimerTask{

    @Override
    public void run() {
        System.out.println("boom");
        new Timer().schedule(new MyTimerTask2(), 4000);
    }
    
}

class MyTimerTask2 extends TimerTask{

    @Override
    public void run() {
        System.out.println("boom");
        new Timer().schedule(new MyTimerTask1(), 2000);
    }
    
}
原文地址:https://www.cnblogs.com/DarrenChan/p/5735175.html