Java 如何强制DriverManager.getConnection()方法调用超时?
我有一个应用程序,它将与MySQL建立DB连接并执行查询。有时调用Java 如何强制DriverManager.getConnection()方法调用超时?,java,timeout,database-connection,Java,Timeout,Database Connection,我有一个应用程序,它将与MySQL建立DB连接并执行查询。有时调用DriverManager.getConnection()方法需要2秒,有时需要30秒。有没有办法控制此方法在2秒后超时 DriverManager.setLoginTimeout()似乎不起作用 实际上,我可以为语句.executeQuery()设置超时,方法是将线程休眠为我的超时值,并在唤醒后关闭连接。但这是连接建立部分,我无法真正设置超时 非常感谢您的帮助。下面是一个如何使用的示例: 如果没有其他选项,您可以始终在单独的线程
DriverManager.getConnection()
方法需要2秒,有时需要30秒。有没有办法控制此方法在2秒后超时
DriverManager.setLoginTimeout()
似乎不起作用
实际上,我可以为语句.executeQuery()设置超时,方法是将线程休眠为我的超时值,并在唤醒后关闭连接。但这是连接建立部分,我无法真正设置超时
非常感谢您的帮助。下面是一个如何使用的示例:
如果没有其他选项,您可以始终在单独的线程中执行调用,如果调用未在2秒内完成,则中止/忽略该线程
编辑
下面是我所想的一个例子:
public class Dummy extends Thread {
private volatile Connection conn = null;
@Override
public void run() {
try {
this.conn = DriverManager.getConnection("foobar") ;
} catch (SQLException e) {
e.printStackTrace();
}
}
static public Connection getConnection() {
Dummy d = new Dummy() ;
d.start() ;
try {
Thread.sleep(2000) ;
} catch (InterruptedException e) {}
return d.conn ;
}
}
然后您可以在代码的其他地方调用静态Dummy.getConnection()方法。一个缺点是,此方法始终需要2秒,但将其更改为在线程完成后立即返回并不太困难。尝试在连接URL或连接池(如果使用池)上设置socketTimeout(时间以毫秒为单位)。注意不要将此值设置得太低,否则会覆盖语句超时值
try {
this.conn = DriverManager.getConnection("url?socketTimeout=2000") ;
} catch (SQLException e) {
e.printStackTrace();
}
或
设置此选项为我解决了超时问题。您可以使用Java中的ExecutorService
接口。下面是您需要做的示例
Future<Boolean> future = executor.submit(YOUR_METHOD);
future.get(TIMEOUT_YOU_NEED, TimeUnit.SECONDS);
Future=executor.submit(您的_方法);
future.get(您需要的超时,TimeUnit.SECONDS);
谢谢codebolt,我不知道这是否是最好的解决方案,但这对我来说很有效。暂停10秒
public class Dummy extends Thread {
private volatile java.sql.Connection conn = null;
private boolean sleep = true;
@Override
public void run() {
try {
String driver = "net.sourceforge.jtds.jdbc.Driver";
Class.forName(driver).newInstance();
//timeout
DriverManager.setLoginTimeout(10);
this.conn = DriverManager.getConnection(url, user, pwd);
sleep = false;
} catch (Exception e) {}
}
public java.sql.Connection getConnection() {
Dummy d = new Dummy() ;
d.start() ;
try {
for(int i=1; i<=10; i++) {
//Wait 1 second
if (d.sleep){
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {}
return d.conn ;
}
}
我扩展了CodeBolt和anpadia的答案,完成了下面的课程。它只有一个静态方法接受所有需要的连接参数,包括超时持续时间。此外,如果发生SQLException和ClassNotFoundException,该方法还将抛出它们
用法:
String connectionUrl = "...";
String user = "...";
String password = "...";
String driver = "org.postgresql.Driver"; // for example
int timeoutInSeconds = 5;
Connection myConnection =
ConnectWithTimeout.getConnection(connectionUrl, user, password, driver, timeoutInSeconds);
实施情况如下:
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
public class ConnectWithTimeout extends Thread {
private static String _url;
private static String _user;
private static String _password;
private static String _driver;
private static volatile Connection _connection = null;
private static volatile boolean _sleep = true;
private static volatile SQLException _sqlException = null;
private static volatile ClassNotFoundException _classNotFoundException = null;
@Override
public void run() {
try {
Class.forName(_driver);
_connection = DriverManager.getConnection(_url, _user, _password);
}
catch (SQLException ex) {
_sqlException = ex;
}
catch (ClassNotFoundException ex) {
_classNotFoundException = ex;
}
_sleep = false;
}
public static Connection getConnection(String url,
String user,
String password,
String driver,
int timeoutInSeconds)
throws SQLException, ClassNotFoundException {
checkStringOrThrow(url, "url");
checkStringOrThrow(user, "user");
checkStringOrThrow(password, "password");
checkStringOrThrow(driver, "driver");
if (timeoutInSeconds < 1) {
throw new IllegalArgumentException(
"timeoutInSeconds must be positive");
}
_url = url;
_user = user;
_password = password;
_driver = driver;
ConnectWithTimeout conn = new ConnectWithTimeout();
conn.start();
try {
for (int i = 0; i < timeoutInSeconds; i++) {
if (_sleep) {
Thread.sleep(1000);
}
}
}
catch (InterruptedException ex) {
}
if (_sqlException != null) {
throw _sqlException;
}
if (_classNotFoundException != null) {
throw _classNotFoundException;
}
return _connection;
}
private static void checkStringOrThrow(String variable, String variableName) {
if (variable == null || variable.length() == 0) {
throw new IllegalArgumentException(
"String is null or empty: " + variableName);
}
}
}
导入java.sql.DriverManager;
导入java.sql.Connection;
导入java.sql.SQLException;
公共类ConnectWithTimeout扩展线程{
私有静态字符串url;
私有静态字符串_用户;
私有静态字符串\u密码;
专用静态字符串驱动程序;
私有静态易失性连接_Connection=null;
私有静态易失性布尔值_sleep=true;
私有静态易失性SQLException _SQLException=null;
私有静态易失性ClassNotFoundException _ClassNotFoundException=null;
@凌驾
公开募捐{
试一试{
Class.forName(_驱动程序);
_connection=DriverManager.getConnection(\u url、\u用户、\u密码);
}
catch(SQLException-ex){
_sqlException=ex;
}
捕获(ClassNotFoundException ex){
_classNotFoundException=ex;
}
_睡眠=假;
}
公共静态连接getConnection(字符串url,
字符串用户,
字符串密码,
字符串驱动程序,
整数时间(秒)
抛出SQLException,ClassNotFoundException{
checkStringOrThrow(url,“url”);
checkStringOrThrow(用户,“用户”);
checkStringOrThrow(密码,“密码”);
checkStringOrThrow(驾驶员,“驾驶员”);
如果(超时秒数<1){
抛出新的IllegalArgumentException(
“TimeOutingSeconds必须为正”);
}
_url=url;
_用户=用户;
_密码=密码;
_司机=司机;
ConnectWithTimeout conn=新的ConnectWithTimeout();
连接开始();
试一试{
对于(int i=0;i
您使用的驱动程序和数据库是什么?如何中止线程?在2秒后中断线程不起作用。如果您认为必须中止线程,您可以随时对其调用stop(),但这是一种不推荐的方法,因此请先阅读文档中的任何潜在陷阱。您也可以在忽略它并继续运行时让它继续运行。抱歉,但是thread.stop()说“如果目标线程等待很长时间(例如,在条件变量上),应该使用中断方法来中断等待。”但在我的情况下,interrupt()没有帮助。我可以知道原因吗?但是我认为setLoginTimeout()实现对于jdbc mysql驱动程序是不可用的。请在答案中包含您的发现。发布者:如果将getConnection()方法设置为静态,则不必创建从未使用过的对象。更进一步,您可以将驱动程序类名、URL、用户名和密码参数设置为getConnection(),并具有相当通用的功能。
String connectionUrl = "...";
String user = "...";
String password = "...";
String driver = "org.postgresql.Driver"; // for example
int timeoutInSeconds = 5;
Connection myConnection =
ConnectWithTimeout.getConnection(connectionUrl, user, password, driver, timeoutInSeconds);
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
public class ConnectWithTimeout extends Thread {
private static String _url;
private static String _user;
private static String _password;
private static String _driver;
private static volatile Connection _connection = null;
private static volatile boolean _sleep = true;
private static volatile SQLException _sqlException = null;
private static volatile ClassNotFoundException _classNotFoundException = null;
@Override
public void run() {
try {
Class.forName(_driver);
_connection = DriverManager.getConnection(_url, _user, _password);
}
catch (SQLException ex) {
_sqlException = ex;
}
catch (ClassNotFoundException ex) {
_classNotFoundException = ex;
}
_sleep = false;
}
public static Connection getConnection(String url,
String user,
String password,
String driver,
int timeoutInSeconds)
throws SQLException, ClassNotFoundException {
checkStringOrThrow(url, "url");
checkStringOrThrow(user, "user");
checkStringOrThrow(password, "password");
checkStringOrThrow(driver, "driver");
if (timeoutInSeconds < 1) {
throw new IllegalArgumentException(
"timeoutInSeconds must be positive");
}
_url = url;
_user = user;
_password = password;
_driver = driver;
ConnectWithTimeout conn = new ConnectWithTimeout();
conn.start();
try {
for (int i = 0; i < timeoutInSeconds; i++) {
if (_sleep) {
Thread.sleep(1000);
}
}
}
catch (InterruptedException ex) {
}
if (_sqlException != null) {
throw _sqlException;
}
if (_classNotFoundException != null) {
throw _classNotFoundException;
}
return _connection;
}
private static void checkStringOrThrow(String variable, String variableName) {
if (variable == null || variable.length() == 0) {
throw new IllegalArgumentException(
"String is null or empty: " + variableName);
}
}
}