多线程的简单应用

            项目里很多地方用到了多线程,最近我负责的一个功能,也用到了多线程,学习总结一下。

            最近在复习操作系统和计算机网络的知识,网络上两台主机的通信,确切来说,是两个进程的通信。进程,运行着的程序。线程,更轻量级,一个进程可以包含一个或多个线程。多线程,同一时间,多个线程在执行。在处理某些业务时,可能业务比较复杂,后续需要及时做出好几种处理,但不要求处理的顺序,这就可以用多线程。

           在Java中,多线程的实现,一般有2种实现方法。一是继承Thread类,二是实现Runnable接口。更推荐使用实现Runnable接口,使用这种方式创建线程可以处理同一个资源,重写run()方法,可以实现自己想要的效果。

           下面将一些本次用到的多线程:

           1、引用jar包,配置application.xml文件,因为我们这个项目用的是spring+Struts2,jar包已经放好了。

        <!-- 配置线程池 -->  
	<bean id ="taskExecutor"  name ="taskExecutor" class ="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" >  
	    <!-- 线程池维护线程的最少数量 -->  
		<property name ="corePoolSize" value ="5" />  
	    <!-- 线程池维护线程所允许的空闲时间 -->  
		<property name ="keepAliveSeconds" value ="30000" />  
	    <!-- 线程池维护线程的最大数量 -->  
		<property name ="maxPoolSize" value ="1000" />  
	    <!-- 线程池所使用的缓冲队列 -->  
		<property name ="queueCapacity" value ="200" />  
	</bean>
	<!-- 配置线程池 结束-->

        2、在自己的类里注入线程池对象。在这里我犯了个低级错误,我用spring注解注入,启动时没问题,运行时报空指针异常。由于项目中用Struts做转发跳转,spring扫描没有做配置,运行时找不到bean,需要自己注入。

private static TaskExecutor threadPool = SpringUtils.getBean("taskExecutor");

package com.ustcsoft.framework.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;


/**
 * 获取spring bean的工具类
 */
public final class SpringUtils implements BeanFactoryPostProcessor {

    private static ConfigurableListableBeanFactory beanFactory; // Spring应用上下文环境

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        SpringUtils.beanFactory = beanFactory;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object 一个以所给名字注册的bean的实例
     * @throws org.springframework.beans.BeansException
     *
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
        return (T) beanFactory.getBean(name);
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name) {
        return beanFactory.containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.isSingleton(name);
    }

    /**
     * @param name
     * @return Class 注册对象的类型
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     * @return
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.getAliases(name);
    }

}

         3、创建实体类,实现Runnable接口,重写run()方法。在run()方法里,可以实现自己的业务。我这儿是一个邮件发送的业务,拼接数据,发送邮件。

package com.ustcsoft.business.service;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.log4j.Logger;

import com.ustcsoft.framework.application.SystemConstants;
import com.ustcsoft.framework.util.MailUtil;

public class SendMailThread implements Runnable {
	
	private String contacts;
	private String payAccountName;
	private String mobile;
	
	private static final Logger logger = Logger.getLogger(SendMailThread.class);
	
	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	private static final String smtp = SystemConstants.SMTP;
	private static final String sender = SystemConstants.SENDER;
	private static final String receiver = SystemConstants.RECEIVER;
	private static final String password = SystemConstants.PASSWORD;
	
	@Override
	public void run() {
		String message = "";
		StringBuffer sb = new StringBuffer();
		sb.append("您有一条借条申请订单待处理。\n");
		sb.append("订单时间:"+ sdf.format(new Date())+"\n");
		sb.append("账户名:"+payAccountName+"\n");
		sb.append("姓名:"+contacts+"\n");
		sb.append("手机号:"+mobile+"\n");
		sb.append("订单来源:微信");
		message = sb.toString();
		String subject = "借条申请订单通知(账户"+ payAccountName +")";
		logger.info("smtp="+smtp+",sender="+sender+",receiver="+receiver+",password="+password+",subject="+subject+",message="+message);
		boolean flag = MailUtil.send(smtp, sender, receiver, password, subject,message);
		logger.info("邮件发送结果:"+flag);
		logger.info("===================SendMailThread执行成功======================");
	}

	public SendMailThread(String contacts,String payAccountName,String mobile){
		this.contacts = contacts;
		this.payAccountName = payAccountName;
		this.mobile = mobile;
	}

	public String getContacts() {
		return contacts;
	}



	public void setContacts(String contacts) {
		this.contacts = contacts;
	}

	public String getPayAccountName() {
		return payAccountName;
	}

	public void setPayAccountName(String payAccountName) {
		this.payAccountName = payAccountName;
	}

	public String getMobile() {
		return mobile;
	}

	public void setMobile(String mobile) {
		this.mobile = mobile;
	}
}

            4、在自己的方法里,创建线程,用线程池处理。

       /**
	 * 借条开户申请确认
	 * 首先调用接口发起借条开通申请,成功后多线程处理后续业务
	 * 调用接口,进行签约代扣申请
	 * 调用接口,进行线签留存证明
	 * 调用接口,给运营人员发送邮件
	 */
	public String confirmOnlineSign(){
		onlineSign = (OnlineSigningInfo) session.getAttribute("onlineSign");
		onlineSign.setAppInterface("0");//表示请求来自移动端
		onlineSign.setPayAccountNo(IDGenerate.genID());
		//借条开户申请,向借条系统发出申请
		String urlString = SystemConstants.wangTingUrl + "do/wx/hydApply";
		Map<String, Object> requestbody = HTTPUtil.beanToMap(onlineSign);;
		log.info("map格式请求参数:"+requestbody);
		String string = HTTPUtil.postByHttpwithMap(urlString, requestbody );
		if(StringUtil.isNotEmpty(string)){
			JSONObject jsonObject = JSONObject.fromObject(string);
			String success = jsonObject.getString("success");
			if("true".equals(success)){
				//申请借条后,账户代扣签约申请
				HytLoadRequestVO hytLoadRequestVO = new HytLoadRequestVO();
				hytLoadRequestVO.setBusinessIds(onlineSign.getBusinessIds());
				hytLoadRequestVO.setChannel("4");//渠道:微信
				hytLoadRequestVO.setMobile(onlineSign.getMobile());
				hytLoadRequestVO.setPayAccountName(onlineSign.getPayAccountName());
				hytLoadRequestVO.setPayAccountNo(onlineSign.getPayAccountNo());
				hytLoadRequestVO.setUserId(onlineSign.getUserId());
				hytLoadRequestVO.setAppInterface(onlineSign.getAppInterface());
				HytAccountLoanSignThread hytLoadSignThread = new HytAccountLoanSignThread(hytLoadRequestVO);
				threadPool.execute(hytLoadSignThread );
				//申请借条后,调用线签接口,留存证据
				OnlineSignThread onlineSignThread = new OnlineSignThread(onlineSign);
				threadPool.execute(onlineSignThread);
				//借条申请后,发送邮件给运营人员,通知运营人员处理订单
				SendMailThread sendMailThread = new SendMailThread(onlineSign.getContacts(),onlineSign.getPayAccountName(),onlineSign.getMobile());
				threadPool.execute(sendMailThread);
				//借条申请后,跳往待审核页面,展示给用户
				return "applicationAuditing";
			}
		}
		return "{\"success\":false}";
	}

          只需要以上几步,就可以简单实现线程池管理多线程,实现多线程编程。其余的,线程状态,线程同步等,本次暂且不说。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坚持是一种态度

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值