Java创建新线程一般有三种方法:
1、继承Thread类。
实现过程:
①、自定义一个类继承Thread类;
②、重写Thread类中的run方法,主要目的是把新创建线程要执行的任务重写在run方法中;
③、调用线程的start方法;
2、实现Runnable接口。
实现过程:
①、定义类实现Runnable接口
②、重写Runnable接口中的run方法把新创建线程要执行的任务重写在run方法中。
③、通过Thread类建立线程对象。
④、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
⑤、调用Thread类的start方法启动新建的线程并调用Runnable接口子类的run方法。
3、通过Callable和Future创建线程。
实现过程:
①、创建Callable接口的实现类,并实现call()方法,该方法将作为线程执行体,且具有返回值。
②、创建Callable实现类的实例,使用FutrueTask类进行包装Callable对象,FutureTask对象封装了Callable对象的call()方法的返回值
③、使用FutureTask对象作为Thread对象启动新线程。
④、调用FutureTask对象的get()方法获取子线程执行结束后的返回值。
并发编程实例:
项目中碰到这样一个问题,用户提交余额调节表到财务系统的同时需要发送邮件反馈提交成功的结果。由于发送邮件耗费的时间相对较长,所以提交成功的提示不能很快响应在系统界面上。此时我们使用并发编程的方案——提交的同时新建一个线程专门来处理发送邮件,这样就不会干扰提交这个任务了。这里采用继承Thread类的方式来实现创建线程。
具体代码如下:
①、自定义一个类继承Thread类;
public class BalanceTableMail extends Thread {
static Logger logger = LoggerFactory.getLogger(BalanceTableMail.class);
}
②、重写Thread类中的run方法,主要目的是把新创建线程要执行的任务重写在run方法中;
public class BalanceTableMail extends Thread {
static Logger logger = LoggerFactory.getLogger(BalanceTableMail.class);
private ActionObject oAction;
public BalanceTableMail(ActionObject oAction) {
super();
this.oAction = oAction;
}
@Override
public void run() {
super.run();
try {
String sAccountName = oAction.getRequestParameterString("accountname");// 单位名称
String sBankName = oAction.getRequestParameterString("bankname");// 银行名称
String sAccountID = oAction.getRequestParameterString("accountid");// 账户卡号
String accountID = sAccountID.substring(sAccountID.length() - 4, sAccountID.length());// 截取账户后四位
String smtp = "***" //
, user = "***" //
, pwd = "***" //
, subject = "【余额调节表提交成功通知】 机构名称:" + sAccountName + "",
content = ",银行名称:" + sBankName + ", 账户尾号:" + accountID + "", from = "space_star_rpa@126.com" //
, to = "***";//
// 提交成功发送邮件
logger.debug("发送邮件。subject:" + subject + ",content:" + content + ",to:" + to);
Mail.send(smtp, user, pwd, subject, content, from, to);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
③、调用线程的start方法;
if ("提交完成!".equals(returnMsg)) {
oAction.success(returnMsg);
new BalanceTableMail(oAction).start();
} else {
oAction.fail(returnMsg);
}
这里有一处细节处理需要注意,新建的线程重写run方法时可能需要传入参数,我们重写的run方法不好传参,怎么处理呢?可以用构造函数传参,也就是这两段代码:
new BalanceTableMail(oAction).start();
private ActionObject oAction;
public BalanceTableMail(ActionObject oAction) {
super();
this.oAction = oAction;
}
当然并发编程不仅仅只是这一点东西,比如还有并发编程同时去调用共享资源就可能会产生脏数据,这时候就用到synchronize关键字进行同步,这涉及到的就是线程安全问题。还有比如锁机制、原子操作等等。这里篇幅优先,先简单的介绍一个并发编程的实例,后续会再写博客介绍并发编程更多的样例和原理。