gpt4 book ai didi

Java:线程安全数据集实现

转载 作者:行者123 更新时间:2023-12-02 01:39:27 26 4
gpt4 key购买 nike

我创建了一个自定义 SQLDataset 实现,它接受 SQL 查询并将 LinkedHashmap 列表返回到请求 Controller ,以在 JSP 中显示或以 Excel 格式下载。

您能否告诉我该方法是否线程安全?

SqlDataset.java

package com.sqle.core;

import com.util.QueryProcessor;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class SqlDataset implements Serializable {
private String query;
private QueryProcessor qp;
private ResultSet rsSet;
private List<LinkedHashMap<String, Object>> rsList = new ArrayList<>();
private ArrayList<String> dataHeader = new ArrayList<>();

public SqlDataset() {}

public SqlDataset(String uquery) {
this.query = uquery;
}

private ResultSet getQueryResult() throws Exception {
qp = new QueryProcessor(query);
this.rsSet = qp.getQueryResultSet();
return this.rsSet;
}

public List<LinkedHashMap<String, Object>> getResult() throws Exception {
return this.getValues(this.getQueryResult());
}

public List<LinkedHashMap<String, Object>> getResult(String query) throws Exception {
this.query = query;
return this.getValues(this.getQueryResult());
}

public int getRowCount() {
return this.rsList.size();
}

public ArrayList getHeaders() {
for (LinkedHashMap<String, Object> aRsList : this.rsList) {
for (Map.Entry<String, Object> dh : aRsList.entrySet()) {
if (!this.dataHeader.contains(dh.getKey()))
this.dataHeader.add(dh.getKey());
}
}
return this.dataHeader;
}

private List<LinkedHashMap<String, Object>> getValues(ResultSet rs) throws SQLException {
ResultSetMetaData rmd = rs.getMetaData();
int columns = rmd.getColumnCount();

while (rs.next()) {
LinkedHashMap<String, Object> row = new LinkedHashMap<>(columns);
for (int i = 1; i <= columns; ++i) {
row.put(rmd.getColumnName(i), rs.getObject(i));
}
this.rsList.add(row);
}
return this.rsList;
}
}

下面是请求 Controller 中编写的代码:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String act = request.getParameter("act").toLowerCase();
RequestDispatcher rd = request.getRequestDispatcher("sqleditor.jsp");

try {
if (act.equalsIgnoreCase("exec")) {
String uqry = request.getParameter("isql");
if (!uqry.isEmpty()) {
SqlDataset sd = new SqlDataset(uqry);
rslist = sd.getResult();
if (sd.getRowCount() > 0) {
headRow = sd.getHeaders();
request.setAttribute("resHead", headRow);
request.setAttribute("result", rslist);
} else {
throw new NoDataException("No data found to display");
}
} else {
throw new NoDataException("Please enter a query");
}
rd.forward(request, response);
} else if (act.equalsIgnoreCase("excel")) {
String uqry = request.getParameter("isql");
if (!uqry.isEmpty()) {
try {
SqlDataset sd = new SqlDataset();
rslist = sd.getResult(uqry);
if (sd.getRowCount() > 0) {
headRow = sd.getHeaders();
response.reset();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=\"" + FILENAME + "\"");
ExcelWriter ew = new ExcelWriter();
ew.initExcelfile(rslist, headRow, response.getOutputStream());
} else {
throw new NoDataException("No data found to download");
}
} catch (Exception evar1) {
throw new AppException(evar1.getMessage());
}
} else {
throw new NoDataException("Please enter a query");
}
}
} catch (SQLException evar2) {
request.setAttribute("errormsg", evar2.getMessage());
rd.forward(request, response);
} catch (NullPointerException evar3) {
request.setAttribute("errormsg", evar3.getMessage());
rd.forward(request, response);
} catch (Exception evar4) {
request.setAttribute("errormsg", evar4.getMessage());
rd.forward(request, response);
}
}

如果多个用户使用此应用程序并连续运行不同的查询,此代码是否有效?

修改后的 SQLdataset 类:

package com.sqle.core;

import com.util.QueryProcessor;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class SqlDataset implements Serializable {

private List<LinkedHashMap<String, Object>> rsList = new ArrayList<>();

public SqlDataset() {}

private ResultSet getQueryResult(String query) throws Exception {
QueryProcessor qp = new QueryProcessor(query);
ResultSet rsSet = qp.getQueryResultSet();
return rsSet;
}

public List<LinkedHashMap<String, Object>> getResult(String query) throws Exception {
return this.getValues(this.getQueryResult(query));
}

public ArrayList getHeaders() {
ArrayList<String> dataHeader = new ArrayList<>();

for (LinkedHashMap<String, Object> aRsList : this.rsList) {
for (Map.Entry<String, Object> dh : aRsList.entrySet()) {
if (!dataHeader.contains(dh.getKey()))
dataHeader.add(dh.getKey());
}
}
return dataHeader;
}

private List<LinkedHashMap<String, Object>> getValues(ResultSet rs) throws SQLException {
ResultSetMetaData rmd = rs.getMetaData();
int columns = rmd.getColumnCount();

while (rs.next()) {
LinkedHashMap<String, Object> row = new LinkedHashMap<>(columns);
for (int i = 1; i <= columns; ++i) {
row.put(rmd.getColumnName(i), rs.getObject(i));
}
this.rsList.add(row);
}
return this.rsList;
}

public int getRowCount() {
return this.rsList.size();
}
}

最佳答案

这取决于你如何使用这个类。

与您的doPost Controller 中的方法对于多个用户来说是线程安全的,因为您创建 new SqlDataset每次都反对。

这意味着它将仅由处理单个请求的线程使用。

您的 Controller 代码是可重入且线程安全的。

顺便说一句,如果您打算使用 SqlDataset作为单例(例如 Spring bean 等) - 它不是线程安全的。它有进程中使用的实例变量 - 这意味着 SqlDataset方法不可重入。

想想他们...

  • 你真的需要private QueryProcessor qp;当您每次在 getQueryResult() 中创建新实例时方法?

  • 你真的需要private ArrayList<String> dataHeader = new ArrayList<>();而你只需从 getHeaders() 返回它- 为什么不直接创建新的 ArrayList之前for在方法内部循环。...等等...

如果将所有内容作为参数传递给方法并返回在方法内创建的所有内容,那么它将是完全线程安全的。

单例可能只有不可变的实例变量(逻辑上几乎是常量),以保持某些设置或属性适用于使用它的任何线程。

关于Java:线程安全数据集实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54652829/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com