站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Java 专题用jive的序列管理器做计数器

用jive的序列管理器做计数器

摘要: 用jive的序列管理器做计数器

</td> </tr> <tr> <td height="35" valign="top" class="ArticleTeitle"> <table width="682" border="0"> <tr> <td width="265"> </td> <td width="378"> 在制作站点计数器时,如果频繁的访问数数库(比如象哪种每增加一人,便写入数据库的作法),当你的站点有很大的访问量时,必然会影响性能。通常的做法有两种,一是启动一个线程定时写入访问量,二是先在内存中保存访问量,只有当访问量达到一定的数量(比如50人)时才写一次数据库。后者的做法更可取,我开始学习jsp时,不知道写计数器,看到jive中的序列管理器很合适“拿来”作计数器用,少许改动后便用它作了自己的第一个主页计数器(用会话session作为计数)。 后来看了一些开源代码,才了解了高手们是如何写计数器的。

package test;
import java.sql.*;
public class SequenceManager {

/**
*记数增量,内存中访问量每满50人时,才将数据写入数据库
*/
private static final int INCREMENT = 50;
</td> </tr> </table>
/**
*下一个访问量
*/
public static long nextID() {
return nextUniqueID();
}

/**
*当前访问量
*/
public static long currentID() {
return oldid;
}

private static long currentID=0l;
private static long oldid=0l;
private static long maxID=0l;//当内存中的访问量大于此值时,更新数据库。

/**
* 创建一个新的序列管理器
*/
public SequenceManager() {
}

/**
* 返回下一个计数id.
*/
public static synchronized long nextUniqueID() {
if (currentID >= maxID) {
getNextBlock(5);//连5次数据库
}
oldid = currentID;
currentID++;
return oldid;
}


private static void getNextBlock(int count) {
java.sql.Connection Conn=null;
java.sql.Statement Stmt=null;
java.sql.ResultSet Rst=null;
if (count == 0) {
System.err.println("在最后一次尝试获取一个ID时失败, 异常中断...");
return;
}
boolean success = false;

try {
String con_string="jdbc:odbc:cwb";
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Conn = DriverManager.getConnection(con_string);
Stmt=Conn.createStatement();
String sqll="select * from count_num";
ResultSet rs=Stmt.executeQuery(sqll);
if (!rs.next()) {
throw new SQLException("Loading the current ID failed. The " +
"jiveID table may not be correctly populated.");
}
long currentID1 = rs.getLong(1);//取数据库中的访问量
long newID = currentID1 + INCREMENT;//访问量加50
sqll="update count_num set num="+newID;
if(currentID>=currentID1) success=Stmt.executeUpdate(sqll)==1;
currentID = currentID1;
maxID = newID;
}
catch( Exception sqle ) {
sqle.printStackTrace();
}
finally {
try { Stmt.close(); }
catch (Exception e) { e.printStackTrace(); }
try { Conn.close(); }
catch (Exception e) { e.printStackTrace(); }
}
if (!success) {
System.err.println("WARNING: failed to obtain next ID block due to " +
"thread contention. Trying again...");
// Call this method again, but sleep briefly to try to avoid thread
// contention.
try {
Thread.currentThread().sleep(75);
} catch (InterruptedException ie) { }
getNextBlock(count-1);//递归调用本方法
}
}
}

测试方法与代码:(在Tomcat 5下调试通过)
先在Access中创建一数据库cwb,并创建表count_num,表中只有一个数字型字段num,并插入一条num为1的记录,jsp测试代码如下:
test.jsp
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="test.*"%>
<%
String login=(String)session.getAttribute("login");
if(login==null){
%>
总访问量:<%=SequenceManager.nextID() %>
<%
session.setAttribute("login","true");
}else{
%>
总访问量:<%=SequenceManager.currentID() %>
<% } %></td> </tr> <tr>


↑返回目录
前一篇: 不设置数据源连接SQL server
后一篇: BBS式虚拟社区系统