我目前正在尝试同时打开2个JDBC连接,这导致两个线程在“getConnection”调用时阻塞。 我使用自编写的TaskManager(这是一个简单的线程池,用于带回调的javafx-Tasks)来提交我的TestConnectionTask,其最大线程数为8.当我将最大线程数设置为1时,一切正常。
以下是相关代码:
提交任务:
TaskManager.getInstance().submitTask(new TestConnectionTask(
new MSSQLConnector(),
this.dbConnectController1.getModel().getHost(),
this.dbConnectController1.getModel().getUser(),
this.dbConnectController1.getModel().getPassword(),
this.dbConnectController1.getModel().getDatabase(),
5-- timeout in seconds
), this::onDB1Connected);
TaskManager.getInstance().submitTask(new TestConnectionTask(
new MySQLConnector(),
this.dbConnectController2.getModel().getHost(),
this.dbConnectController2.getModel().getUser(),
this.dbConnectController2.getModel().getPassword(),
this.dbConnectController2.getModel().getDatabase(),
5-- timeout in seconds
), this::onDB2Connected);
TestConnectionTask类:
public class TestConnectionTask extends Task<SavingDBConnector>
{
private final DBConnector connector;
private final String host;
private final String user;
private final String password;
private final String database;
private final int timeout;
public TestConnectionTask(DBConnector connector, String host, String user, String password, String database, int timeout)
{
super();
updateTitle("Verbindungstest");
this.connector = connector;
this.host = host;
this.user = user;
this.password = password;
this.database = database;
this.timeout = timeout;
}
@Override
protected SavingDBConnector call() throws Exception
{
updateProgress(0L, 2L);
updateMessage("Verbindungsversuch");
try (Connection conn = this.connector.openConnection(this.host, this.user, this.password, this.database, this.timeout))
{
updateProgress(1L, 2L);
}
catch (Exception e)
{
updateMessage("Beim Herstellen der Verbindung ist ein Fehler aufgetreten");
throw e;
}
updateProgress(2L, 2L);
updateMessage("Verbindung erfolgreich hergstellt");
return new SavingDBConnector(this.connector, this.host, this.user, this.password, this.database, this.timeout);
}
}
DBConnector类:
public abstract class DBConnector
{
private final String jdbcClassName;
private final String jdbcSubprotocol;
private boolean jdbcClassLoaded;
public DBConnector(String jdbcClassName, String jdbcSubprotocol)
{
this.jdbcClassName = jdbcClassName;
this.jdbcSubprotocol = jdbcSubprotocol;
this.jdbcClassLoaded = false;
}
public Connection openConnection(String host, String user, String password, String database, int timeout) throws SQLException, ClassNotFoundException
{
if (!this.jdbcClassLoaded)
{
Class.forName(this.jdbcClassName);
this.jdbcClassLoaded = true;
}
Properties properties = new Properties();
properties.setProperty("User", user);
properties.setProperty("Password", password);
if (timeout > 0)
{
properties.setProperty("LoginTimeout", Integer.toString(timeout));
}
Connection conn = DriverManager.getConnection(String.format("jdbc:%s://%s", this.jdbcSubprotocol, host), properties);
conn.setCatalog(database);
return conn;
}
}
实现MSSQL和MySQL只是简单地构建它:
super("com.microsoft.sqlserver.jdbc.SQLServerDriver", "sqlserver");
and
super("com.mysql.jdbc.Driver", "mysql");
最后但并非最不重要的是TaskThreadPool,它是我的Project-Spefific TaskManager的超类
public class TaskThreadPool
{
private int maxThreadCount;
private int currentThreadCount;
private final Object lockCurrentThreadCount;
private final ConcurrentLinkedQueue<TaskWithCallback<?>> queue;
public TaskThreadPool()
{
this.maxThreadCount = 1;
this.currentThreadCount = 0;
this.lockCurrentThreadCount = new Object();
this.queue = new ConcurrentLinkedQueue<>();
}
public void setMaxThreadCount(int maxThreadCount)
{
this.maxThreadCount = maxThreadCount;
}
public int getMaxThreadCount()
{
return this.maxThreadCount;
}
public <T> void submitTask(Task<? extends T> task, TaskCallback<T> callback)
{
this.queue.offer(new TaskWithCallback<>(task, callback));
synchronized (this.lockCurrentThreadCount)
{
if (this.currentThreadCount < this.maxThreadCount)
{
this.currentThreadCount++;
Thread thread = new Thread(this::threadRun);
thread.setDaemon(true);
thread.start();
}
}
}
private void threadRun()
{
while (true)
{
TaskWithCallback<?> taskWithCallback;
while ((taskWithCallback = this.queue.poll()) != null)
{
taskWithCallback.run();
}
synchronized (this.lockCurrentThreadCount)
{
// Sonst möglicherweise tote Tasks
if (this.queue.isEmpty())
{
this.currentThreadCount--;
break;
}
}
}
}
private class TaskWithCallback<T> implements Runnable
{
private final Task<? extends T> task;
private final TaskCallback<T> callback;
public TaskWithCallback(Task<? extends T> task, TaskCallback<T> callback)
{
this.task = task;
this.callback = callback;
}
@Override
public void run()
{
this.task.run();
if (this.callback != null)
{
Platform.runLater(() -> this.callback.onTaskCompleted(this.task.getValue()));
}
}
}
public interface TaskCallback<T>
{
public void onTaskCompleted(T result);
}
}
答案 0 :(得分:0)
我现在在DBConnector中使用以下同步静态方法一个接一个地打开连接作为解决方法
private synchronized static Connection getConnection(String url, Properties info) throws SQLException
{
return DriverManager.getConnection(url, info);
}
仍然期待找到一个允许我打开多个并行连接的解决方案