0 0

线程做短信发送服务,存在的问题。我没有积分了请见谅0

知道自己的代码写的很烂,但是还是忍不住要贴上来,求指点啊。
我现在在做一个短信发送的服务,我的想法是用线程来发送短信,但是一直存在问题,如果一次发送短信过多,创建线程多了的话就会有内存异常。所以现在改成了,控制最多只创建100个线程来发送,但是同事说这种做法很有问题。
第一sendThreadCount这个变量没有同步,多个线程同时访问的话会有问题.
第二在创建100个线程也很占资源。
关于第一个问题,我就没有想明白哪有问题了,static 的int 变量也需要同步么?
第二个问题是我真的不知道该如何控制能更好了。代码已贴了,请大伙帮忙看看。


public class ServiceThread implements Runnable {
	private int timeout;// 轮询间隔时间毫秒
	List returnHistoryList = new ArrayList();// 返回的发送历史
	List sendingList = new ArrayList<Map>();// 发送的短信队列
	public static int sendThreadCount = 0;//标识发送线程数量
	public ServiceThread() {
		this.timeout = 10000;
	}

	public void run() {
		sendThreadCount = 0;
		while (SmsManager.run) {
			try {
				// 1、查找发送表已发送状态的记录
				findResutedlMsg();
				// 3、写入历史表,从发送表中删除
				insertHistory();
				// 4、查找发送表中待发送状态的记录
				findSending();
				// 发送待发送的短信
				sendQueue();
			} catch (Exception e) {
			}
			reset();
			try {
				Thread.sleep(timeout);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		clear();
	}

	//查找发送了的数据
	private void findResutedlMsg() throws Exception {
		returnHistoryList = SmsManager.getJdbcTemplate().queryForList(
				"select send_id from t_sms_send where send_state in (2,3,4,5)");
	}

	// 将返回的历史记录写入历史表
	private void insertHistory() throws Exception {
		int count = returnHistoryList.size();
		if (count > 0) {
			StringBuffer send_ids = new StringBuffer();
			for (int i = 0; i < count; i++) {
				Map map = (Map) returnHistoryList.get(i);
				send_ids.append(map.get("send_id")+",");
			}
			send_ids.deleteCharAt(send_ids.lastIndexOf(","));
			StringBuffer sqlstr = new StringBuffer();
			sqlstr.append("insert into t_sms_send_history( ");
			sqlstr.append("select * FROM t_sms_send where send_id in (");
			sqlstr.append(send_ids.toString());
			sqlstr.append(")");
			Connection conn = SmsManager.getJdbcTemplate().getDataSource().getConnection();
			Statement stat = null;
			try {
				conn.setAutoCommit(false);
				stat = conn.createStatement(); 
				stat.execute(sqlstr.toString());
				stat.execute("delete from t_sms_send where send_id in ("+send_ids.toString()+")");
				conn.commit();
			} catch (Exception e) {
				SmsManager.sendMsgToServicer(e,"平台短信服务器出现异常");
			}finally{
				if(!stat.isClosed()){
					stat.close();
				}
				if(!conn.isClosed()){
					conn.close();
				}
			}
		}
	}

	// 查找400平台发送表中待发送的记录
	private void findSending() throws Exception {
		sendingList = SmsManager
				.getJdbcTemplate()
				.queryForList(
						"select send_id,customer_id,msg_type,msg_content,phone_nums from t_sms_send where send_state = 1 and smsg_id is null limit 100");
	}

	// 发送短信
	private void sendQueue() throws Exception {
		for (int i = 0; i < sendingList.size(); i++) {
			if(sendThreadCount <= 100){
				Map map = (Map) sendingList.get(i);
				SmsManager.getJdbcTemplate().execute("update t_sms_send set smsg_id = '10000' where send_id = "+map.get("send_id"));
				Map msg = new HashMap();
				msg.put("send_id", map.get("send_id"));
				msg.put("customer_id", map.get("customer_id"));
				msg.put("phone_nums", map.get("phone_nums"));
				msg.put("msg_content", map.get("msg_content"));
				Thread trecv = new SendThread(msg);
				trecv.setName("SMS_"+sendThreadCount);
				sendThreadCount++;
				trecv.start();
			} 
		}
	}

	/**
	 * 重置发送数据
	 */
	private void reset() {
		returnHistoryList = new ArrayList();
		sendingList = new ArrayList<Map>();
	}
}


//发送短信线程
class SendThread extends Thread {
	private Map msg = null;
	public SendThread(Map msg){
		this.msg = msg;
	}
	public void run() {
		String sMsgId = "";
		try {
			String strMsg = msg.get("msg_content").toString();
			String phone_nums = msg.get("phone_nums").toString();
			if(!Public.isNotNull(phone_nums)){
				return;
			}
			//发送短信
			SmsManager.send(strMsg,phone_nums);
			returun;
		} catch (Exception e) {
		} finally{
			ServiceThread.sendThreadCount--;
		}
	}
}
2013年1月17日 23:04

6个答案 按时间排序 按投票排序

1 0

第一个问题我觉得应该没问题吧。i++不存在先i+1再把结果赋值给i的过程,不管几个线程都是将内存中唯一的那个i自增。
第二个问题可能需要用线程池来缓解不断创建、销毁线程的压力吧,线程池的话java自己就实现了一个可以拿来用

2013年1月18日 02:18
0 0

1: sendThreadCount  这个变量处理有问题,未同步if(sendThreadCount <= 100)和  sendThreadCount++在多线程坏境下肯定出错,用AtomicInteger
2: 线程未重用,每次都要新建一个线程,用完就销毁了。。。干嘛不用线程池。。

2013年1月22日 08:44
0 0

像这个比较简单的线程创建和线程池的问题,建议用并发包来完成。

2013年1月18日 21:30
0 0

1,你把一个任务理解成了线程,任务是轻量级的,线程是比较重的,所以需要重用(线程池),一般10个线程足够了,发送短信最终瓶颈在io,线程多了是浪费;

2,sendThreadCount加个volatile修饰吧,虽然并不影响代码运行;

2013年1月18日 14:45
0 0

1. 多处未同步
2. 可采用线程池
3. 未考虑失败情况
4. 可加个缓冲区

其他的还有 不多说了

2013年1月18日 12:11
0 0

i++这个操作是非线程安全的,可以用AtomicInteger代替int型变量。
jdk里有现成的线程池组件。

2013年1月18日 09:51

相关推荐

    JAVA模拟多线程给多用户发送短信

    值得注意的是,本文虽然没有提供实际的短信发送功能实现,但从逻辑上讲,我们可以在UserThread类的run()方法中嵌入使用第三方短信服务API的代码,从而实现真正的短信发送功能。在使用短信服务商的API进行发送时,...

    VB6用winsock实现多线程客户端登录与短信发送

    标题中的“VB6用winsock实现多线程客户端登录与短信发送”指的是使用Visual Basic 6(VB6)编程语言,结合Winsock控件来构建一个支持多线程的客户端应用,该应用能够进行登录操作并能发送短信。Winsock是Windows上...

    cmpp2.0短信网关发送短信代码(java)

    CMPP2.0短信网关发送短信代码是Java开发者用于与中国移动通信集团的短信服务进行交互的一种技术实现。CMPP(China Mobile Short Message Peer-to-Peer)2.0协议是移动运营商提供的一种通信协议,主要用于短信业务的...

    C# UDP多线程发送接收

    2. 需要注意同步问题,避免发送线程和接收线程同时访问UdpClient实例,可以使用锁或其他同步机制。 五、C# UDP多线程接收 1. 创建接收线程,持续监听特定端口,接收到数据后进行处理。 2. 接收线程通常采用循环结构...

    短信免费版倥件 (V5 多线程版)

    【标题】中的“短信免费版倥件(V5 多线程版)”指的是一个专门用于短信发送的软件工具,其版本为V5,并且具备多线程处理能力。在IT行业中,这样的软件通常用于批量发送短信,可能是企业用于市场营销、客户服务或者...

    QT 多线程TCP服务器与客户端

    QT框架中的多线程TCP服务器与客户端编程是一个关键的领域,尤其在开发高效、响应迅速的网络应用时。本文将深入探讨如何利用QT库,特别是QT5.11.1版本,来构建多线程的TCP服务器和客户端,以及QThread在其中的作用。 ...

    控制台多线程短信猫程序

    "控制台多线程短信猫程序"就是一个很好的例子,它利用多线程技术在控制台环境下实现短信发送功能。在这个项目中,我们主要关注的是如何在控制台环境中通过DLL动态链接库与硬件设备(短信猫)进行交互,并利用多线程...

    串口通信多线程接收数据,发送数据

    在本文中,我们将深入探讨如何使用多线程实现串口通信,包括数据的接收和发送。 首先,我们需要理解串口通信的基本原理。串口通信通常基于RS-232标准,通过一对数据线进行单向或双向的数据传输。通信参数如波特率、...

    MFC线程间发送消息

    另外,线程安全问题也需要注意,比如在多个线程访问同一资源时,应采取同步机制,如互斥量或信号量,以防止数据竞争。 8. **`ThreadCommunicate`文件**:这可能是实现线程间通信的具体代码示例,可能包含了创建线程...

    java短信平台发送源码

    4. **线程安全**:如果需要大量并发发送短信,应考虑线程安全问题。可以使用线程池(ExecutorService)来管理并发任务,避免过多的并发导致资源耗尽。 5. **异常处理**:处理网络异常、解析异常以及短信服务返回的...

    java 软件开发短信定时发送

    在Java软件开发中,短信定时发送是一项常见的功能,尤其在企业级应用、通知服务或营销自动化系统中。本文将深入探讨如何实现这个功能,并结合Java技术栈的特点进行讲解。 首先,我们要理解Java软件开发的基本原理。...

    libevent 多线程 HTTP post服务器

    而多线程技术则允许服务器同时处理多个客户端请求,提高服务效率。HTTP POST是HTTP协议中的一个方法,用于向服务器提交数据。 **描述分析:** 描述中提到的“libevent 多线程 HTTP post服务器”表明这是一个利用...

    PB 11.5短信发送源码(纯api)

    【PB 11.5短信发送源码(纯api)】是基于PowerBuilder 11.5开发的一个短信发送程序,它使用API接口与短信猫设备进行通信,实现了高效、稳定的短信发送功能。以下是该程序的主要特点和相关知识点: 1. **多线程**:...

    使用SMPP发送短信

    使用SMPP发送短信是一项在企业级应用中常见的功能,它允许开发者使用SMPP(Short Message Peer-to-Peer)协议,与短信中心(SMSC)进行通信,实现短信的发送、接收、报告等功能。在实际应用中,开发者通常会面临实时...

    VS2010 同步TCP SOCKET应用编程 服务器 客户端 消息解析 多线程

    在监听线程中,服务器一旦接受一个连接,就创建一个与该玩家对应的线程,用于接收该玩家发送的信息,并根据该玩家发送的信息提供相应的服务。 有多少个玩家连接,就创建多少个对应的线程。玩家退出游戏室,其对应的...

    iOS两个线程间嵌套发送同步消息的demo

    比如,线程A向线程B发送同步消息,而线程B又向线程A发送同步消息,两者都会等待对方完成,从而形成僵局。因此,合理设计线程间的通信逻辑,避免同步消息的嵌套使用,是防止死锁的关键。 在提供的资源"Sync"中,可能...

    C#版手机短信发送系统

    7. **多线程编程**:为了提高系统的响应速度,短信发送通常会在后台线程中执行,不影响用户界面的交互。C#中的Thread或Task类可以帮助实现这一点。 8. **异常处理**:为了应对可能出现的错误,如网络故障、短信服务...

    c# Socket 多线程 分包 发送/接受数据

    在Socket通信中,多线程可以用来分别处理接收和发送数据,或者处理多个客户端连接,避免因为单线程的阻塞导致整个程序的响应变慢。例如,一个线程负责接收数据,另一个线程负责处理接收到的数据并发送响应。 3. **...

    MFC多线程 工作者线程 用户界面线程

    在Windows编程领域,MFC(Microsoft Foundation Classes)是微软提供的一套C++库,用于简化Windows应用程序的开发,包括创建用户界面和实现多线程功能。MFC中的多线程技术使得程序能够同时执行多个任务,提高应用的...

    API 短信网关发送SMS SP

    API短信网关是现代通信系统中的重要组成部分,它允许服务提供商(SP)通过程序化接口与短信服务中心(SMSC)进行交互,实现自动化发送、接收和处理短信。在这个系统中,"API 短信网关发送SMS SP" 的概念是指服务提供...

Global site tag (gtag.js) - Google Analytics