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