一.
假设在一个Connection的CallableStatement上,正执行一个耗时的存储过程,这个时候强制把这个   Connection关闭掉(简单地调用close方法),发现这个连接还一直存在,直到这个存储过程执行完毕。问题:一个连接要关闭,必须等待在它上面的所有操作都完毕之后?   JDK的说法是:Releases this Connection object's database and JDBC resources immediately instead of waiting for them to be automatically released.
   按照JDK的说法,当调用close时,该Connection应该立即被释放,但是为什么现在的测试中,它却是等待的呢?二.
如果在main中启动了另外的线程,而其中的某一个正在执行一个耗时的存储过程,在这种情况下,在main中执行System.exit操作,整个程序的结束必须等待这个线程的结束?奇怪的是,如果某一个线程也是在不断地执行任务,诸如简单的打印任务之类,该线程却会马上结束。难道是说,线程会因为自己执行的任务不同也变得不同?三.
测试程序:
public class Test{    public static void main(String args[]){
        final TestThread thread1=new TestThread();
        TestThread2 thread2=new TestThread2();        JFrame frame=new JFrame();
        frame.setTitle("Test");
        frame.setSize(260, 240);
        frame.getContentPane().setLayout(new FlowLayout());
        
        JButton jButton=new JButton("Test");
        jButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ae){
                System.out.println("\n指定关闭程序...");
                thread1.closeConnection();
                System.exit(0);
            }
        });        JPanel p = new JPanel();
        p.setLayout(new BorderLayout());
        p.add(jButton,BorderLayout.NORTH);
        frame.getContentPane().add(p);
        frame.setVisible(true);        
        thread1.start();
        thread2.start();
    }}class TestThread extends Thread
{
    Connection conn=null;    public void run(){
        String connStr="jdbc:db2:sample";
        CallableStatement proc = null; 
        
        try{
            Class.forName("COM.ibm.db2.jdbc.app.DB2Driver").newInstance();            conn=DriverManager.getConnection(connStr);            //执行的存储过程是一个耗时的存储过程
            proc = conn.prepareCall("call IvanZhang.Test(?)");
            proc.registerOutParameter(1, Types.INTEGER); 
            proc.execute();
            int result=proc.getInt(1);
            System.out.println("\n"+Thread.currentThread().getName()+" "+result);
            
            closeConnection();
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }    public void closeConnection(){
        try{
            if(conn!=null){
                //conn.commit();
                conn.close();
                conn=null;
            }
        }
        catch(SQLException sqlexc){
            sqlexc.printStackTrace();
        }
    }
}class TestThread2 extends Thread
{
    public void run(){
        try{
            for(int i=0;i<100;i++){
                System.out.print(i+" ");
                Thread.sleep(1000);
            }
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
}
//存储过程drop procedure IvanZhang.Test@
create procedure IvanZhang.Test
(
    out outNum int
)
SPECIFIC IvanZhang.Test
LANGUAGE SQLbegin
    DECLARE i INTEGER DEFAULT 0;
    
    while i < 20000 do
        insert into IvanZhang.test values('1','2');
        
          commit work ;
      
          delete from IvanZhang.test;        commit work ;
          
          set processNum=i;
          
          set i=i+1;
      end while;      
end@
谢谢。 

解决方案 »

  1.   

    一般的任务和数据库操作毕竟有很大的不同,数据库操作,比如你说的调用一个耗时的存储过程,存储过程的执行过程不在java线程的控制范围内,线程只能处于一种排它性的等待状态,等待DBMS返回处理结果,线程再继续。此时你调用close()关闭连接,不一定就成功,在调用Connection.close()之后,可以用isClosed()检测一下,如果为假则说明这个问题。关于jdbc中的close的说法,应该是一般情况下相对与gc来说的吧,立即释放资源而不是等待自动回收。
      

  2.   

    close 跟存储过程有什么关系?存储过程一旦执行就由数据库控制的.即便Connection.close,也不关它的事.
      

  3.   

    感谢两位回答。我也觉得存储过程一旦执行就由数据库控制的,这边的这个连接不应该非要等待不可。另外,第2个问题呢?如果那个线程不停止?就不能用Sysetem.exit让整个程序退出?
      

  4.   

    可以将TestThread 设为Daemon的,这样Main Thread结束,TestThread也会结束的……
      

  5.   

    存储过程的运行是在数据库里运行的
    这和你JAVA系统的CONNECTION是没有关系的
    你告诉数据库运行一个存储过程,数据库就启动一个进程去执行这个过程
    这个时候就等于和JAVA系统没有关系了,JDBC此时已经是空闲状态了
    所以你断不断连接和存储过程的运行无关