1、runnable的职责
2、策略模式在thread中的应用
3、模拟营业大厅叫号机程序
------------------------------------------------------runnable的职责-------------------------------------------------------------------
runnable源码如下:
package java.lang;
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
在很多软文以及一些书籍中,经常会提到,创建线程有两种方式,第一种是构造一个Thread,第二种是实现Runnable接口,这种说法是错误的,最起码不是严谨的,在JDK代表线程的就只有Thread这个类,我们在前面分析过,线程的执行单元就是run方法,你可以通过继承Thread然后重写run方法实现自己的业务逻辑,也可以实现Runnable接口实现自己的业务逻辑,代码如下:
@Override
public void run() {
if (target != null) {
target.run();
}
}
如果构造Thread时传递了runnable,则会执行runnable的run方法。
否则需要重写thread的run方法。
上面代码是Thread run方法的源码,实现线程有两种方法是一种是创建一个Thread一种是实现Runnable接口,这种说法是不严谨的。准确的说应该是,创建线程只有一种方式那就是构造thread类,而实现线程的执行单元则有两种方式,第一种是重写thread的run方法,第二种是实现runnable接口的run方法,并且将runnable实例用作构造Thread的参数。
Thread和runnable之间的关系是怎样的呢?
Thread负责线程本身相关的职责和控制,而runnable则负责逻辑执行单元的部分。
------------------------------------------------------策略模式在thread中的应用-----------------------------------------------------
前面说了,无论是runnable的方法,还是thread类本身的run方法(事实上Thread类也是实现了Runnable的接口)都是想将线程控制本身和业务逻辑的运行分离开来,达到指责分明、功能单一的原则,这一点与GoF设计模式中的策略设计模式很相似,我们来看看什么是策略设计模式,然后再来对比Thread和runnable两者之间的关系。
相信很多人都做过JDBC的开发,线面我们在这里做一个简单的查询操作,只不过是把数据的封装部分抽象成了策略接口
package lambda;
import java.sql.ResultSet;
public interface RowHandler<T> {
T handle(ResultSet rs);
}
RowHandler接口只负责对从数据库中查询出来的结果集进行操作,至于最终返回成什么样的数据结构,那就需要你自己去实现,类似于Runnable接口,代码示例如下:
package lambda;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class RecordQuery {
private final Connection con;
public RecordQuery(Connection con) {
this.con = con;
}
public <T> T query(RowHandler<T> handler,String sql,Object... params ) throws SQLException {
try(PreparedStatement stmt = con.prepareStatement(sql)){
int index = 1;
for(Object param:params) {
stmt.setObject(index++,param );
}
ResultSet res = stmt.executeQuery();
//自己实现数据的返回格式
return handler.handle(res);
}
}
}
RecordQuery中的query只负责将数据查询出来,然后调用RowHandler进行数据封装,至于将其封装成什么数据结构,那就的看自己怎么处理了,下面我们来看看这样做到底有什么好处?
上面这段代码的好处就是可以用query方法应对任何数据库的查询,返回结构的不同只会因为你传入的RowHandler思维不同而不同,同样RecordQuery只负责数据的获取,而RowHandler则负责数据的加工,职责分明,每个类均功能单一,相信通过简单的示例就已经清楚的了解Thread和Runnable之间的关系了。
注意:重写Thread的run方法和显示Runnable接口的run方法还有一个很重要的不同,那就是Thread类的run方法是不能共享的,也就说A线程不能把B线程的run方法当作自己的执行单元,而使用runnable接口则很容易就能实现这一点,使用同一个runnable的实例(作为参数)构造不同的Thread实例。这样使用起来更为灵活。
------------------------------------------------------模拟营业大厅叫号机程序-------------------------------------------------------
一个简单的小例子随后附上源码。