任何人都可以告诉我在下一个任务允许启动之前强制执行java中的一个任务的方法吗?具体来说,我想编辑下面的代码,以便在调用下一个标记的两行之前完成第一行标记的两行代码。
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String idString = req.getParameter("id");
Long id = new Long(idString);
//complete the actions specified on next two lines
School school = new SchoolDAO().findSchool(id);
req.setAttribute("school", school);
//before even starting the actions specified on the next two lines
List<CourseSummary> coursesummaries = new CourseSummaryDAO().findAllcsum(id);
req.setAttribute("coursesummaries", coursesummaries);
jsp.forward(req, resp);
}
为了更好地理解费尔南多的建议,我将学校的一些相关部分包括在内:
public class SchoolDAO extends DataAccessObject{
public School findSchool(Long id) {
ResultSet rs = null;
PreparedStatement statement = null;
Connection connection = null;
try {
connection = getConnection();
String sql = "select * from schoolprog where id=?";
statement = connection.prepareStatement(sql);
statement.setLong(1, id.longValue());
rs = statement.executeQuery();
if (!rs.next()) {return null;}
return readSchool(rs);
}
catch (SQLException e) {throw new RuntimeException(e);}
finally {close(rs, statement, connection);}
}
private School readSchool(ResultSet rs) throws SQLException {
Long id = new Long(rs.getLong("id"));
String spname = rs.getString("spname");
String spurl = rs.getString("spurl");
School school = new School();
school.setId(id);
school.setName(spname);
school.setUrl(spurl);
return school;
}
}
同样,CourseSummaryDAO包含:
public class CourseSummaryDAO extends DataAccessObject{
public List<CourseSummary> findAllcsum(Long sid) {
LinkedList<CourseSummary> coursesummaries = new LinkedList<CourseSummary>();
ResultSet rs = null;
PreparedStatement statement = null;
Connection connection = null;
try {
connection = getConnection(); //this is the line throwing null pointer error
String sql = "select * from coursetotals where spid=?";
statement = connection.prepareStatement(sql);
statement.setLong(1, sid);
rs = statement.executeQuery();
//for every row, call read method to extract column
//values and place them in a coursesummary instance
while (rs.next()) {
CourseSummary coursesummary = readcsum("findAll", rs);
coursesummaries.add(coursesummary);
}
return coursesummaries;
}
catch (SQLException e) {throw new RuntimeException(e);}
finally {close(rs, statement, connection);}
}
程序破解的行是:
connection = getConnection(); //
答案 0 :(得分:2)
如果您有两个应该连续执行的任务(即一个任务在下一个任务开始之前完成),那么最佳答案是同步执行它们。例如,假设task1()
和task2()
是任务:
// Wrong way:
Runnable r1 = new Runnable(){
public void run() {
task1();
}};
Runnable r2 = new Runnable(){
public void run() {
// Wait for r1 to finish task1 ... somehow
task2();
}};
// Right way:
Runnable r = new Runnable(){
public void run() {
task1();
task2();
}};
在您的情况下,看起来像 doGet
调用只有在获得两个任务的结果时才会返回。这表明在这种情况下你根本不应该使用线程。只需在请求主题上按顺序调用task1()
和task2()
。
编辑
查看doGet
方法以及随后添加的两个类,看起来,就像处理已经顺序/串行一样。也就是说,第一个“任务”在第二个“任务”开始之前结束。
getConnection()
抛出NullPointerException
的问题(很可能)与异步无关。但是,如果没有看到getConnection()
和完成堆栈跟踪的代码,我就无法确定。
答案 1 :(得分:1)
在Java中,所有内容通常按顺序执行 ,这意味着在下一行开始执行任何操作之前,给定的代码行将完全执行。此规则的例外是线程发挥作用。线程允许多个代码块同时执行。因为你没有在你的程序中使用任何线程(你知道你是否,不要担心),所以保证前两行代码将在接下来的两行开始执行之前完成。
所以,你的问题似乎并不是你的代码“乱序”运行。你的错误很可能是在getConnection()
方法中的某个地方,如果这就是投掷NPE的那个。
答案 2 :(得分:0)
以下是一个示例(有关详细信息,请参阅Java Threads waiting value)
import java.util.concurrent.CountDownLatch;
class MyTask implements Runnable
{
CountDownLatch signal;
public MyTask(CountDownLatch signal)
{
this.signal = signal;
}
public void run()
{
System.out.println("starting task");
for (int i = 0; i < 10000000; i++)
Math.random();
//call when the task is done
signal.countDown();
}
}
public class Program
{
public static void main(String[] args) {
int workers = 1;
CountDownLatch signal = new CountDownLatch(workers);
new Thread(new MyTask(signal)).start();
try {
// Waits for all the works to finish ( only 1 in this case)
signal.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task is done");
}
}
这只是一个建议,也许有更好的设计:
import java.util.concurrent.CountDownLatch;
public class SchoolDAO extends DataAccessObject implements Runnable {
Long id;
CountDownLatch signal;
School searchResult;
public SchoolDAO(Long id, CountDownLatch signal)
{
this.id = id;
this.signal = signal;
}
public void run()
{
searchResult = findSchool(id);
signal.countDown();
}
// the other methods didn't change
}
现在你可以在doGet()中调用它:
CountDownLatch signal = new CountDownLatch(1);
SchoolDAO dao = new SchoolDAO(id, signal);
new Thread(dao).start();
try {
signal.await();
} catch (InterruptedException e)
{
e.printStackTrace();
}
School result = dao.searchResult;