ThreadLocal,LinkedBlockingQueue,线程池 获取数据库连接2改进

package com.ctl.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

import com.ctl.util.ConfigUtils;
import com.ctl.util.LogUtil;

public class ThreadLocalBlockingQueueUtils {
	private static ThreadLocal<LinkedBlockingQueue<Connection>> queueHoder = new ThreadLocal<LinkedBlockingQueue<Connection>>();
	public static int num = 0;
	private static String driver;
	private static String url;
	private static String username;
	private static String password;
	private static int threadPoolMaxNum;

	private static int threadPoolMinNum;
	private static LogUtil log;
	// \u6570\u636E\u5E93\u7C7B\u578Boracle mysql db2
	private static String databasetype;
	public static int getThreadPoolMaxNum() {
		return threadPoolMaxNum;
	}

	public static int getThreadPoolMinNum() {
		return threadPoolMinNum;
	}

	public static String getUrl() {
		return url;
	}

	public static String getUsername() {
		return username;
	}

	public static String getPassword() {
		return password;
	}

	static {
		log = new LogUtil();
		databasetype = ConfigUtils.getType("databasetype");
		threadPoolMaxNum = Integer.parseInt(ConfigUtils
				.getType("threadPoolMaxNum"));
		threadPoolMinNum = Integer.parseInt(ConfigUtils
				.getType("threadPoolMinNum"));
		if (databasetype.equals("mysql")) {
			driver = ConfigUtils.getType("mysql.driver");
			url = ConfigUtils.getType("mysql.url");
			username = ConfigUtils.getType("mysql.username");
			password = ConfigUtils.getType("mysql.password");
		} else if (databasetype.equals("oracle")) {
			driver = ConfigUtils.getType("oracle.driver");
			url = ConfigUtils.getType("oracle.url");
			username = ConfigUtils.getType("oracle.username");
			password = ConfigUtils.getType("oracle.password");
		}
		try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			System.out.println(e.getMessage());
		}
		CreateConnection createConn = new CreateConnection();
		createConn.setDaemon(true);
		createConn.start();
	}

	public static synchronized LinkedBlockingQueue<Connection> getQueue() {
		LinkedBlockingQueue<Connection> queue = queueHoder.get();
		if (queue == null) {
			queue = new LinkedBlockingQueue<Connection>(threadPoolMaxNum);
			queueHoder.set(queue);
			return queue;
		}
		return queue;
	}

	// static void start() {
	// Tom tom = new Tom();
	// tom.start();
	// for(;;){
	// try {
	// Thread.sleep(200);
	// System.out.println("/*************"+getConnection()+"*************/");
	// } catch (InterruptedException e) {
	// }
	// }
	// }
	//
	// public static void main(String[] args) {
	// ThreadLocalBlockingQueueUtils.start();
	// }

	public static Connection getConnection() {
		// System.out.println("进入getConnection");
		class GetConnectionClazz extends Thread {
			LinkedBlockingQueue<Connection> queue = ThreadLocalBlockingQueueUtils
					.getQueue();
			private Connection conn;
			private int queueSize;
			public int getQueueSize() {
				return queueSize;
			}
			public Connection getConn() {
				return conn;
			}
			public synchronized void run() {
				// System.out.println("进入getConnection run()");
				try {
					// System.err.println("-----"+conn+"--------");
					while (conn == null) {// 很重要没有该while循环当按F5不断刷新时,只要有一个取出来为空后面的全为空
						conn = queue.poll(2, TimeUnit.SECONDS);
					}
					queueSize=queue.size();
					// System.err.println("*******"+conn+"*********");
					// if (conn != null) {
					// System.err.println("\u3010" + queue.size() + "\u3011"
					// + "getConnecion\u6210\u529F\uFF1A" + conn);
					// }
				} catch (InterruptedException e) {
					log.WriteLine("getConnection", e.getMessage());
				}
			}
		}
		GetConnectionClazz jj = new GetConnectionClazz();
		jj.start();
		try {
			jj.join();
		} catch (InterruptedException e) {
			log.WriteLine("getConnection()", e.getMessage());
		}
		log.WriteLine("getConnection()","\u3010" + jj.getQueueSize() + "\u3011"+ "getConnecion\u6210\u529F\uFF1A" + jj.getConn());
		return jj.getConn();
	}

}

// class GG extends Thread {
// public void run() {
// for (;;){
// try {
// ThreadLocalBlockingQueueUtils.getConnection();
// Thread.sleep(300);
// } catch (Exception e) {
// }
// }
// }
// }
/**
 * @descritpion 创建数据库连接的线程类
 * @author Administrator
 *
 */
class CreateConnection extends Thread {
	LinkedBlockingQueue<Connection> queue = ThreadLocalBlockingQueueUtils
			.getQueue();
	LogUtil log = new LogUtil();

	public synchronized void run() {
		boolean result = false;
		while (true) {
			try {
				Random rand=new Random();
				int num=ThreadLocalBlockingQueueUtils.getThreadPoolMaxNum()-ThreadLocalBlockingQueueUtils.getThreadPoolMinNum();
				int randSize=rand.nextInt(num)+1;
				if(queue.size()>=randSize){
					Thread.sleep(100);
					continue;
				}
				Connection conn = null;
				conn = DriverManager.getConnection(
						ThreadLocalBlockingQueueUtils.getUrl(),
						ThreadLocalBlockingQueueUtils.getUsername(),
						ThreadLocalBlockingQueueUtils.getPassword());
				if (conn != null) {
					result = queue.offer(conn, 1, TimeUnit.SECONDS);
				} else {
					// System.out.println("DriverManager.getConnection is null");
					log.WriteLine("CreateConnection.run()",
							"DriverManager.getConnection()返回 null");
					continue;
				}
				if (result == false) {
					Thread.sleep(100);
					log.WriteLine("CreateConnection.run()",
							"已达到最大连接数queue.size()=" + queue.size());
					// System.out.println("已经满了size=【" + queue.size() + "】");
				} else {
					log.WriteLine("CreateConnection.run()",
							"\u3010" + queue.size() + "\u3011"
									+ "createConnection success:" + conn);
					// System.out.println("\u3010" + queue.size() + "\u3011"
					// + "createConnection success:" + conn);
				}
			} catch (InterruptedException e) {
				// e.printStackTrace();
				log.WriteLine("getConnection", e.getMessage());
				// System.err.println(e.getMessage());
			} catch (SQLException e) {
				log.WriteLine("getConnection", e.getMessage());
				// e.printStackTrace();
				// System.err.println(e.getMessage());
			}
		}
	}
}

ThreadLocal,LinkedBlockingQueue,线程池 获取数据库连接2改进,布布扣,bubuko.com

时间: 2024-08-08 09:40:40

ThreadLocal,LinkedBlockingQueue,线程池 获取数据库连接2改进的相关文章

ThreadLocal,LinkedBlockingQueue,线程池 获取数据库连接

<pre name="code" class="java">package com.ctl.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; import java.ut

简单介绍一下线程池和数据库连接池的原理

当客户端请求的数据量比较大的时候,使用线程池可以节约大量的系统资源,使得更多的CPU时间和内存可以高效地利用起来.而数据库连接池的使用则将大大提高程序运行效率,同时,我们可以通过其自身的管理机制来监视数据库连接的数量.使用情况等.本文我们主要就介绍一下线程池和数据库连接池的原理,接下来我们一起来了解一下这一部分内容. 线程池的原理: 其实线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的流程如下:先启动若干数量的线程,并让这些线程都处于睡眠状态,当客户端有一个新请求时,就会唤醒线程池中的某

ThreadLocal与线程池使用的问题

感谢博主的这篇分享,见 https://www.cnblogs.com/qifenghao/p/8977378.html 在今天的面试中,突然被考官问了这个问题,当时脱口而出的是 threadlocal容易会有内存泄漏,需要注意remove.其实自己仔细想想,这个回答太过于结果了,没有思考为何要配合线程池的时候,去remove. 注意,这里需要你的jdk版本为1.8及以上,否者清将lambda表达式改为匿名内部类 问题的版本 1 public class ThreadLocalAndPool {

当ThreadLocal碰上线程池

ThreadLocal使用 ThreadLocal可以让线程拥有本地变量,在web环境中,为了方便代码解耦,我们通常用它来保存上下文信息,然后用一个util类提供访问入口,从controller层到service层可以很方便的获取上下文.下面我们通过代码来研究一下ThreadLocal. 新建一个ThreadContext类,用于保存线程上下文信息 public class ThreadContext { private static ThreadLocal<UserObj> userReso

源码分析—ThreadPoolExecutor线程池三大问题及改进方案

前言 在一次聚会中,我和一个腾讯大佬聊起了池化技术,提及到java的线程池实现问题,我说这个我懂啊,然后巴拉巴拉说了一大堆,然后腾讯大佬问我说,那你知道线程池有什么缺陷吗?我顿时哑口无言,甘拜下风,所以这次我再回来思考一下线程池的实现原理 源码分析 ThreadPoolExecutor构造器 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, Blo

dbcp2连接池获取数据库连接Connection

一.先来看看手工创建的方式 public static Connection getConnection() { Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection( "jdbc:mysql://127.0.0.1:3306/mytable?useUnicode=true&characterEncoding=ut

ThreadLocal遇到线程池时, 各线程间的数据会互相干扰, 串来串去

最近遇到一个比较隐蔽而又简单地问题,在使用ThreadLocal时发现出现多个线程中值串来串去,排查一番,确定问题为线程池的问题,线程池中的线程是会重复利用的,而ThreadLocal是用线程来做Key的所以在使用线程池的时候要特别注意ThreadLocal. ThreadLocal数据是在线程创建时绑定在线程上的, 所以解决方法是在使用数据之前调用remove() 移除掉之前的其他线程产生的数据 解决方法 重构remove方法 @Override public void remove() { 

线程池和数据库连接池

什么是线程池和工作机制? 当一个程序中若创建大量线程,并在任务结束后销毁,会给系统带来过度消耗资源,以及过度切换线程的危险,从而可能导致系统崩溃.为此我们应使用线程池来解决这个问题. 首先创建一些线程,它们的集合成为线程池,当服务器接收到一个客户请求后,就从线程池中取出一个空闲的线程位置服务,服务结束后不关闭该线程,而是将该线程还回到线程池中.当线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后,它就在内部找有无空闲的线程,再把任务交给内部某个空闲的线程,一个

扫盲大队-线程池

一.是什么 在聊线程池之前,想厘清并发和并行的概念. 并发(Concurrency)的实质是一个物理CPU(也可以多个物理CPU) 在若干道程序(或线程)之间多路复用,并发性是对有限物理资源强制行使多用户共享以提高效率. 从微观角度来讲:所有的并发处理都有排队等候,唤醒,执行等这样的步骤,在微观上他们都是序列被处理的,如果是同一时刻到达的请求(或线程)也会根据优先级的不同,而先后进入队列排队等候执行. 从宏观角度来讲:多个几乎同时到达的请求(或线程)在宏观上看就像是同时在被处理. 并行(Para