Previously on OOP:
How to read a file line by line, split the line into several fields, and fill them to Java Generics was the topic discussed in the last article.
在本文中,我们会进入Tread章节的学习。Thread的程序并不在本课程的考试范围内,所以各位宝宝们不用纠结于这一章的代码,把重点放在理论部分的理解上。
现在有一个非常简单的需求:
这个需求可以用线程来实现。
既然选用线程来实现,那么我们首先要创建一个线程。Thread类的constructor需要的参数是一个Runnable Interface的子类的实例。虽然这个分析过程已经出现过了很多次,但是本黄鸭还是要再重申一遍。一个Interface的实例是不能直接创建的。想要实例的话,只能先创建一个该Interface的子类,可以用普通的类,也可以用inner classes,最后再创建子类的实例。以上整个过程还可以用一个Lambda expression来代替。
本段代码就采用了Lambda expression来创建Runnable Interface的子类的实例。里面的abstract function被改写为while循环体,功能是不停地打印“Duck”字符串。
“不停地打印”和我们的所需要的“每隔一秒钟打印一次”是不同的。要解决这个问题,请看下面的一种方案。
本段代码相比上一段增加了try-catch block,还有sleep()函数。
本黄鸭决定先分析一下try-catch block。这是一种Exception handler的写法,目的是为了handle Thread.sleep()调用时可能出现的Exception。如果对于Thread.sleep()函数有信心(事实上确实不会出太大的问题),那么不写这里的try-catch block也是可以的。在catch block中,有两种写法:
(1)ignore the problem,什么也不做,就当无事发生,继续执行循环体。
(2)打印一点别的字符串,以说明这里曾经出过Exception,再返回到main函数。
再看一下sleep()函数。这个函数能不能实现我们的需求呢?答案是否定的。因为在过完sleep()函数规定的时间之后,线程会进入Runnable state,即排队等待Java virtual machine的scheduler分配CPU时间,直到被scheduler选中,才能回到Running state,开始打印字符串“Duck”。所以从用户的角度上来看,实际sleep的时间一般都要比给定的长。
虽然使用sleep()函数不是一个最佳方案,但是不管怎么说,我们的线程已经创建好了。使用线程的object reference调用start()函数,就能让这个线程在程序运行的时候开始执行。
接下来,让我们了解一下multi-tasking。当线程在打印“Duck”的时候,打开一个输入对话框,线程还能继续执行吗?
如何创建一个输入对话框的是Graphic User Interface章节的内容,会在后面的文章中重点讲解。JOptionPane类可以提供四种弹出对话框,分别是:
(1)showConfirmDialog:有三个按钮yes, not,andcancel
(2)showInputDialog
(3)showMessageDialog:目的在于inform the user that something happened。
(4)showOptionDialog
最后,Thread的执行可以被打断,只要用刚才创建的Thread的object reference来调用interrupt()函数即可。
调用这个函数时,不管线程处于什么样的状态,都会立即被打断,并且收到一个Exception。所以,线程的代码中最好包含一个Exceptionhandler,以备interrupt()触发Exception的剧情。
欢迎使用本黄鸭编写的小程序~
微信公众号二维码:
领取专属 10元无门槛券
私享最新 技术干货