0

I'm currently learning JDBC. And I try to update the product information and insert a log at the same time.

private void testTransaction() { try { // Get Connection Connection connection = ConnectionUtils.getConnection(); connection.setAutoCommit(false); // Execute SQL Product product = new Product(1, 4000d); productService.updateProduct(connection, product); Log log = new Log(true, "None"); logService.insertLog(connection, log); // Commit transaction connection.commit(); } catch (Exception e) { e.printStackTrace(); } finally { ConnectionUtils.closeConnection(); } } 

When using single thread, it would be fine.

 @Test public void testMultiThread() { testTransaction(); } 

But When I using multi-thread, even start one thread, the process would terminate automatically.

 @Test public void testMultiThread() { for (int i = 0; i < 1; i++) { new Thread(this::testTransaction).start(); } } 

After debugging, I found that it was Class.forName() function in ConnectionUtils cause this situation.

public class ConnectionUtils { static private String url; static private String driver; static private String username; static private String password; private static Connection connection = null; private static ThreadLocal<Connection> t = new ThreadLocal<>(); static { try { Properties properties = new Properties(); properties.load(new FileReader("src/main/resources/jdbcConnection.properties")); driver = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); Class.forName(driver); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() { try { connection = DriverManager.getConnection(url, username, password); } catch (Exception e) { e.printStackTrace(); } finally { t.set(connection); } return connection; } } 

The process will terminate at Class.forName(). I found this by adding two print funcion before and after the statement. And only the former works.

System.out.println("Before"); Class.forName(driver); System.out.println("After"); 

The console only print the Before and doesn't show any exception information. I want to know that why multi-thread in java will cause this situation and how to solve this problem.

2
  • Do you have a thread dump or stacktrace of any exceptions? Commented Aug 30, 2020 at 3:22
  • No, there is no exceptions printed in console. Commented Aug 30, 2020 at 3:40

2 Answers 2

2

This is more likely your test method complete before your other threads and the test framework is not waiting (junit?). You need to wait until the threads have completed. You should use an Executors, this is more convinient.

@Test public void testMultiThread() { Thread[] threads = new Thread[1]; for (int i = 0; i < threads.length; i++) { threads[i] = new Thread(this::testTransaction); threads[i].start(); } // wait thread completion for (Thread th : threads) { th.join(); } } 
Sign up to request clarification or add additional context in comments.

Comments

1

Junit will terminate all your thread as long as the test method finish.

In your case, test will finish when the loop ends, it doesn't care whether testTransaction has finished. It has nothing to do with class.forName , maybe it's just because this method exceute longer.

you can check this answer

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.