由close引发的故事
由close引发的故事
艳沐石 发表于4年前
由close引发的故事
  • 发表于 4年前
  • 阅读 9
  • 收藏 0
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

摘要: 编码中,很多不注意的小地方,往往让程序变得效率低下。保持一个良好的习惯,程序更健壮。

最近在写一些多线程的任务,有时候任务处理多起来,一些不好的编程毛病就变得恐惧起来。

1. 采用框架,在读取信息时候有些慢,于是我用原生jdbc来完成的。代码如下:


public List<String> getIsbns(int offset, int size) {
		try {
			Connection con = dataSource.getConnection();
			Statement stmt = con.createStatement();
			ResultSet rs = stmt.executeQuery("select pisbn from amazon_book where flag is null limit " + offset + ", " + size);
			List<String> list = new ArrayList<String>(size);
			while (rs.next()) {
				list.add(rs.getString(1));
			}
			return list;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}



由于,我没有及时的关闭Connection,导致程序在运行不久后出现了问题。


情况描述:
1. 采用直连方式,每次都需要创建连接,而连接又未释放,导致保持过多数据库连接资源,数据查询结果响应降低。
2. 采用数据库连接池方式,由于没有及时释放资源,导致数据库连接池达到最大的时候,使得其他数据库请求等待,导致数据库访问有一种静默的样子。

查看java.sql.Connection源码,发现有如下注释


/**
     * Releases this <code>Connection</code> object's database and JDBC resources
     * immediately instead of waiting for them to be automatically released.
     * <P>
     * Calling the method <code>close</code> on a <code>Connection</code>
     * object that is already closed is a no-op.
     * <P>
     * It is <b>strongly recommended</b> that an application explicitly
     * commits or rolls back an active transaction prior to calling the
     * <code>close</code> method.  If the <code>close</code> method is called
     * and there is an active transaction, the results are implementation-defined.
     * <P>
     *
     * @exception SQLException SQLException if a database access error occurs
     */
    void close() throws SQLException;



【我们应该手动释放不应用的资源,而不是等待被自动回收】,如果资源被消耗殆尽,只能等待虚拟机自己去回收了,这样的程序不是高效的。



2. 在字符写入文件时候,对于OutputStream没有及时close

try {
		File f = new File(bookFolder + "page.html");
		System.out.println(f.getPath());
		if (!f.getParentFile().exists()) {
			f.getParentFile().mkdirs();
		}
		if (!f.exists()) f.createNewFile();
		IOUtils.copy(new ByteArrayInputStream(doc.toString().getBytes()), new FileOutputStream(f));
	} catch (Exception e) {
		throw new RuntimeException(e.getMessage(), e);
	}



原因:  
操作系统的中打开文件的最大句柄数受限所致,常常发生在很多个并发用户访问服务器的时候.因为为了执行每个用户的应用服务器都要加载很多文件(new一个socket就需要一个文件句柄),这就会导致打开文件的句柄的缺乏.

解决:
尽量把类打成jar包,因为一个jar包只消耗一个文件句柄,如果不打包,一个类就消耗一个文件句柄.
java的垃圾回收不能关闭网络连接打开的文件句柄,如果没有执行close()(例如:java.net.Socket.close())则文件句柄将一直存在,而不能被关闭.你也可以考虑设置socket的最大打开数来控制这个问题.

所以养成良好的编码习惯,在对数据库访问,文件操作完毕后,通过finally模块将其关闭,以免发生不必要的问题。


  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 2
博文 40
码字总数 20499
×
艳沐石
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: