can you look at my connection pool if it is a possible way to implement it?
public class ConnectionPool {
private static List<DBConnection> pool = null;
private static int available = 0;
private ConnectionPool() {}
public static DBConnection getConnection() {
if (pool == null) {
pool = new ArrayList<DBConnection>();
for (int i = 0; i < 3; i++) {
try {
pool.add(new DBConnection());
available++;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
if (pool.size() > 0) {
available--;
return pool.remove(available);
} else {
return null;
}
}
public static void returnConnection(DBConnection c) {
pool.add(c);
available++;
}
}
I'm using only one array and the client should ask the connection pool for a connection use it and then return it to the connection pool.
Connection connection = ConnectionPool.getConnection();
connection.execute("insert into users values('"+user.getUsername()+"', '"+user.getPassword()+"', '"+user.getGroup()+"', '"+banned+"', '"+broker+admin+sharehodler+company+"')");
ConnectionPool.returnConnection(connection);
connection = null;
Please I need feedback on this implementation. Thank you
There are some points that make this implementation very problematic.
Thread safety. What if several threads work with the pool? You are not locking the list on read/write access.
Static maximum pool size of 3 connections, also you immediately create all of them, whether they are needed or not. A common strategy is to create a bunch of connections and create some more when needed, until the allowed/configured maximum is reached.
You only have static methods. It should be possible to have several pools, meaning you need instances of ConnectionPool.
No way to pass host+dbname+user+password to the connections that are created.
You don't deal with 'broken' connections - you may have to re-create a connection if an existing one screwed up. This is far more relevant than I thought before I started using pools.
Use config values instead of static values, see point #2
Lastly: sure, it's interesting to write this stuff yourself - but if you need a pool for a project, pick an existing one, such as c3p0 or the tomcat connection pool.
I'm sure there's more to point out, but unless these are fixed, there's no use in continuing.
One big problem with your pool implementation is that you pass the naked connection to the callers of the pool. This means that someone can obtain a connection from your pool, close it, and then return it to the pool. This is bad.
The normal way around this problem is to wrap the return connection objects using delegation, and make them ignore calls to the close method (or even better, make close() safely return the underlying connection to the pool).
Other major issues:
What happens if a connection is returned in the middle of a transaction?
What happens if a connection is somehow corrupted or disconnected? Does it stay in the pool?
All in all, you should reuse an existing connection pool implementation rather than writing your own. These days, many type 4 drivers have their own connection pools included right within the driver.
Some thoughts:
Your code is NOT thread safe. Maybe work on this.
Too much code in getConnection(). Is lazy initialisation really
needed ?
available is useless, can be substitute by pool.size().
AFAIK,
your getConnection() method need to be changed to in order to retrieve Connection object only.
Preparing connection and pooling should be taken away from the getConnection() method and added in such a way that when ConnectionPool class is loaded first time.
Also you need to handle some other attributes as well like connection timeout, purging etc in order to make it work for all scenarios.
Make it thread safe as well.
Other members have already suggested lots of things. I have some model implementation, thought of sharing it for new visitors. Here is code:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
abstract class ObjectPool<T> {
private ConcurrentLinkedQueue<T> pool;
ScheduledExecutorService executorService;
ObjectPool(int minObjects) {
pool = new ConcurrentLinkedQueue<T>();
for (int i = 0; i < minObjects; i++) {
pool.add(createObject());
}
}
ObjectPool(final int minObjects, final int maxSize, final long interval){
pool = new ConcurrentLinkedQueue<T>();
for (int i = 0; i < minObjects; i++) {
pool.add(createObject());
}
executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleWithFixedDelay(new Runnable(){
public void run() {
int size = pool.size();
while(size > maxSize){
pool.remove();
}
Iterator i = pool.iterator();
while(i.hasNext()){
T t = (T) i.next();
if(checkExpiry(t)){
System.out.println("Expiry existed...");
i.remove();
}
}
while(pool.size() < minObjects){
System.out.println("Adding more objects to pool");
pool.add(createObject());
}
}
}, interval, interval, TimeUnit.MILLISECONDS);
}
public T borrowObject() {
if (pool.peek() == null)
return createObject();
return pool.remove();
}
public void addObject(T obj) {
if (obj == null)
return;
pool.add(obj);
}
public abstract T createObject();
public abstract boolean checkExpiry(T t);
}
class MultithreadQuery extends Thread{
private ObjectPool<Connection> pool;
private int threadNo;
String query;
MultithreadQuery(ObjectPool<Connection> pool,int threadNo, String query){
this.pool = pool;
this.threadNo = threadNo;
this.query = query;
}
#Override
public void run(){
Connection con = pool.borrowObject();
Statement stmt;
try {
stmt = con.createStatement();
System.out.println("Query started for thread->"+ threadNo);
ResultSet rs=stmt.executeQuery(query);
while(rs.next())
System.out.println(rs.getInt(1)+" "+rs.getString(2)+" "+rs.getString(3));
System.out.println("closing connection....");
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
pool.addObject(con);
System.out.println("Query ended for thread->"+ threadNo);
}
}
public class ObjectPoolPatternDemo {
ObjectPool<Connection> pool;
public void setUp(){
pool = new ObjectPool<Connection>(4, 10, 1) {
#Override
public Connection createObject() {
Connection con;
try {
con = DriverManager.getConnection("URL","Username","Password");
return con;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
public boolean checkExpiry(Connection conn) {
boolean expiryFlag = false;
try {
if(conn.isClosed())
expiryFlag = true;
} catch (SQLException e) {
e.printStackTrace();
}
return expiryFlag;
}
};
}
public static void main(String[] args) throws SQLException {
ObjectPoolPatternDemo oppd = new ObjectPoolPatternDemo();
oppd.setUp();
ExecutorService es = Executors.newFixedThreadPool(4);
String query = "select * from TABLE";
es.execute(new MultithreadQuery(oppd.pool,1,query));
es.execute(new MultithreadQuery(oppd.pool,2,query));
es.execute(new MultithreadQuery(oppd.pool,3,query));
es.execute(new MultithreadQuery(oppd.pool,4,query));
es.execute(new MultithreadQuery(oppd.pool,5,query));
es.execute(new MultithreadQuery(oppd.pool,6,query));
es.shutdown();
try {
es.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("finally completed...");
}
}
Related
This question already has answers here:
JUnit terminates child threads
(6 answers)
Closed 2 years ago.
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.
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();
}
}
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
I have a class which looks like that:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
public class ConnectionPool {
private HikariDataSource hds;
private final String propertyFileName;
public ConnectionPool(String propertyFileName) {
if (propertyFileName == null) {
throw new IllegalArgumentException("propertyFileName can't be null");
}
this.propertyFileName = propertyFileName;
reloadFile();
}
public void reloadFile() {
if (hds != null) {
hds.close();
}
hds = new HikariDataSource(new HikariConfig(propertyFileName));
}
public HikariDataSource getHikariDataSource() {
return hds;
}
public String getPropertyFileName() {
return propertyFileName;
}
public void executeQuery(final String sql, final CallBack<ResultSet, SQLException> callBack) {
new Thread(new Runnable() {
#Override
public void run() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = hds.getConnection();
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
callBack.call(resultSet, null);
} catch (SQLException e) {
callBack.call(null, e);
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException ignored) {}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException ignored) {}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException ignored) {}
}
}
}
}).start();
}
public void executeUpdate(final String sql, final CallBack<Integer, SQLException> callBack) {
//TODO
}
public void execute(final String sql, final CallBack<Boolean, SQLException> callBack) {
//TODO
}
public void connection(final String sql, final CallBack<Connection, SQLException> callBack) {
//TODO
}
}
The problem is that the reloadFile() method can be called from a different thread as hds is used. So it's possible that hds is closed while I use a connection object of it in another thread. What's the best way to solve this problem? Should I wait a few seconds after creating the new HikariDataSource object befor closing the old one (until the queries are finished)?
Edit: Another question: Should hds be volatile, so that the changes of hds are visible for all threads?
Have had a very very quick and brief look in the source code in HikariDataSource. In its close(), it is calling its internal HikariPool's shutdown() method, for which it will try to properly close the pooled connections.
If you want to even avoid any chance that in-progress connection from force closing, one way is to make use of a ReadWriteLock:
public class ConnectionPool {
private HikariDataSource hds;
private ReentrantReadWriteLock dsLock = ....;
//....
public void reloadFile() {
dsLock.writeLock().lock();
try {
if (hds != null) {
hds.close();
}
hds = new HikariDataSource(new HikariConfig(propertyFileName));
} finally {
dsLock.writeLock().unlock();
}
}
public void executeQuery(final String sql, final CallBack<ResultSet, SQLException> callBack) {
new Thread(new Runnable() {
#Override
public void run() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
dsLock.readLock().lock();
try {
connection = hds.getConnection();
// ....
} catch (SQLException e) {
callBack.call(null, e);
} finally {
// your other cleanups
dsLock.readLock().unlock();
}
}
}).start();
}
//....
}
This will make sure that
multiple thread can access your datasource (to get connection etc)
Reload of datasource needs to wait until thread using the datasource to complete
No thread is able to use the datasource to get connection when it is reloading.
Why exactly are you trying to cause HikariCP to reload? Many of the important pool parameters (minimumIdle,maximumPoolSize,connectionTimeout,etc.) are controllable at runtime through the JMX bean without restarting the pool.
Restarting the pool is a good way to "hang" your application for several seconds while connections are closed and rebuilt. If you can't do what you need through the JMX interface, Adrian's suggestion seems like quite a reasonable solution.
Other solutions are possible, but have more complexity.
EDIT: Just for my own entertainment, here is the more complex solution...
public class ConnectionPool {
private AtomicReference<HikariDataSource> hds;
public ConnectionPool(String propertyFileName) {
hds = new AtomicReference<>();
...
}
public void reloadFile() {
final HikariDataSource ds = hds.getAndSet(new HikariDataSource(new HikariConfig(propertyFileName)));
if (ds != null) {
new Thread(new Runnable() {
public void run() {
ObjectName poolName = new ObjectName("com.zaxxer.hikari:type=Pool (" + ds.getPoolName() + ")");
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
HikariPoolMXBean poolProxy = JMX.newMXBeanProxy(mBeanServer, poolName, HikariPoolMXBean.class);
poolProxy.softEvictConnections();
do {
Thread.sleep(500);
} while (poolProxy.getActiveConnections() > 0);
ds.close();
}
}).start();
}
}
public HikariDataSource getHikariDataSource() {
return hds.get();
}
public void executeQuery(final String sql, final CallBack<ResultSet, SQLException> callBack) {
new Thread(new Runnable() {
#Override
public void run() {
...
try {
connection = getHikariDataSource().getConnection();
...
}
}
}).start();
}
}
This will swap out the pool (atomically) and will start a thread that waits until all active connections have returned before shutting down the orphaned pool instance.
This assumes that you let HikariCP generate unique pool names, i.e. do not set poolName in your properties, and that registerMbeans=true.
A few options:
Synchronize all access to the data source so that only one thread can ever be messing with it. Not scaleable, but workable.
Roll your own connection pooling, such as Apache Commons Pooling so that each access, regardless of thread, requests a data source and pooling creates one as necessary. Can mess with data ACID, just depends on whether dirty data is needed, when data is flushed, transactionality, etc.
Each thread could also have its own data source using ThreadLocal so that each thread is totally independent of each other. Again, quality of data might be an issue, resources might be an issue if you've got "lots" of threads (depends on your definition) and too many open connections cause resource issues on either the client or server.
I have created a database object according to the singleton pattern. The database object contains 2 methods: connect() and update().
The update should run multithreaded, meaning that I cannot put synchronized in the update method signature (I want users to access it simultaneously not one at a time).
My problem is that I want to make sure that 2 scenarios according to this flows:
A thread 1 (user1) is the first to create an instance of the DB and thread 2 (user2) is calling the connect() and update() method to this DB - should not give NullPointerException even if by the time that user2 is doing the update() the connect from user1 is not done.
update() should not include synchronized (because of the reason I mentioned above).
Thanks for all the helpers!
SingeltonDB
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SingeltonDB {
private static DBconnImpl db = null;
private static SingeltonDB singalDb = null;
Lock dbLock;
private SingeltonDB(String username, String password) {
db = new DBconnImpl();
}
public static boolean isOpen() {
return (db != null);
}
public synchronized static SingeltonDB getInstance(String username,
String password) throws Exception {
if (db != null) {
throw (new Exception("The database is open"));
} else {
System.out.println("The database is now open");
singalDb = new SingeltonDB(username, password);
}
db.connect(username, password);
System.out.println("The database was connected");
return singalDb;
}
public synchronized static SingeltonDB getInstance() throws Exception {
if (db == null) {
throw (new Exception("The database is not open"));
}
return singalDb;
}
public void create(String tableName) throws Exception {
dbLock = new ReentrantLock();
dbLock.lock();
db.create(tableName);
dbLock.unlock();
}
public User query(String tableName, int rowID) throws Exception {
if (db == null) {
System.out.println("Error: the database is not open");
return null;
}
return (db.query(tableName, rowID));
}
public void update(String tableName, User user) throws Exception {
if (db == null) {
System.out.println("Error: the database is not open");
return;
}
db.update(tableName, user);
}
}
Main
public class Main {
public static void main(String[] args) throws Exception {
Creator cr= new Creator(new UserContorller());
Thread t1 = new Thread(cr);
t1.start();
Producer pr = new Producer(new UserContorller());
Thread t2 = new Thread(pr);
t2.start();
/*
* Consumer cn = new Consumer(new UserContorller()); Thread t2 = new
* Thread(cn); t2.start();
*/
}
}
class Creator implements Runnable {
UserContorller uc;
public Creator(UserContorller uc) {
this.uc = uc;
}
#Override
public void run() {
try {
uc = new UserContorller("MyAccount", "123");
uc.createTable("table1");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Producer implements Runnable {
UserContorller uc;
public Producer(UserContorller uc) {
this.uc = uc;
}
#Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
uc.saveUser("table1", i, "User", i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
UserContorller uc;
public Consumer(UserContorller uc) {
this.uc = uc;
}
#Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
System.out.println(uc.getUser("table1", i));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Note: The post below was written in the perspective of both users using the same credentials (hidden from them) to connect to the database. If users employ different credentials, the idea of a singleton db object is purposeless, each user should have their own connection object, and of course then connection details are passed on from the user to the Db via whatever represents the user in the program (here the thread instances apparently).
The main issue in the implementation you provided is that the getinstance method requires its caller to know the connection details, or assume that the connection has already been done. But neither threads could nor should know in advance if the Db has been opened already -- and design wise it's a mistake to hand them the responsibility of explicitely opening it. These threads are work threads, they shouldn't be concerned about Db configuration details.
The only sane way to handle this situation is to have these configuration parameters held by the Db object directly, or better yet another object in charge of providing it (it's the factory pattern).
However, if you want first your code to work with minimal changes, get rid of the parameter less getinstance method, have any thread requiring the Db object to use the remaining variant of that method, passing along the correct parameters, and change it to return the instance if it exists, or create it otherwise, without raising an exception. I believe that it's what #Dima has been trying to explain in his answer.
Connect once, when creating the singleton (in the constructor, perhaps).
Have a synchronized static method (getInstance or something), that checks if an instance exists, creates and connects as necessary, and returns the instance. By following this protocol, you ensure that threads always get a connected Db object ready to be used.
The users will call that method to get the singleton instance, and call update or whatever they want on it, it does not need to be synchronized.
Let's say we've got an SQL database (hsqldb) and want to run a number of queries on it which do not modify the content.
This takes a long time for some queries and I would like to run the queries in multiple threads.
So my question is: what is the best way to implement this?
I did not find any good samples to do this so I came up with the following (which I would love to get some comments on).
First, very briefly in words:
I use thread-safe collections to access the queries and to put the results in. The queries are executed in a number of worker threads. The results are processed in the main thread which checks for new results until all threads are finished.
Now the code:
Create thread-safe collections of queries and results:
ConcurrentLinkedQueue<String> queries = new ConcurrentLinkedQueue<String>()
ConcurrentLinkedQueue<ResultSet> sqlResults = new ConcurrentLinkedQueue<ResultSet>();
Create a number of threads and start them (edited):
ExecutorService executorService = Executors.newFixedThreadPool(4);
for(int i=0; i<4; i++){
executorService.execute(new QueryThread(sqlResults, queries));
}
Within the thread class QueryThread a connection is opened and queries are executed as long as there are any left:
private class QueryThread implements Runnable {
private ConcurrentLinkedQueue<ResultSet> sqlResults;
private ConcurrentLinkedQueue<String> queries;
public QueryThread(ConcurrentLinkedQueue<ResultSet> sqlResults, ConcurrentLinkedQueue<String> queries){
this.sqlResults = sqlResults;
this.queries = queries;
}
#Override
public void run(){
Connection connThr = null;
try{
try {
connThr = DriverManager.getConnection(dbModeSave, "sa", "");
connThr.setAutoCommit(false);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String currentQuery;
do {
currentQuery = queries.poll(); // get and remove element from remaining queries
if (currentQuery != null) { // only continue if element was found
try {
Statement stmnt = connThr.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
try {
ResultSet resultSet = stmnt.executeQuery(currentQuery);
sqlResults.add(resultSet);
} catch (SQLException e) {
// (Do something specific)
} finally {
stmnt.close();
}
} catch (SQLException e) {
// (Do something specific)
}
}
} while (currentQuery != null);
} finally {
if (connThr != null) {
try {
connThr.close();
} catch (SQLException e) {
// Nothing we can do?
}
}
}
}
}
From the original thread I check, if the threads are all finished and therefore all queries were processed (edited).
while (!executorService.isTerminated()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
while (!sqlResults.isEmpty()) {
ResultSet result = sqlResults.poll();
//process result and close it in the end
}
}
Java standard sulution for parallel processing is ThreadPoolExecutor. Try it.
How to handle the thread pool where one is polling while the other should update new incoming data after processing.
The program execution beings in a controller class which has a main method and thread pool:
The main class Controller
public static void main(String[] args) throws InterruptedException {
RunnableController controller = new RunnableController();
Accumulator acque = new Accumulator();
controller.initializeDb();
controller.initialiseThreads(acque);
controller.initialUpdate(acque);
}
The Run method for Polling class:
public void run() {
int seqId = 0;
List<KpiMessage> list = null;
while(true) {
try{
list = fullPoll(seqId);
if (!list.isEmpty()) {
accumulator.manageIngoing(list);
}
} catch (Exception e){
e.printStackTrace();
}
}
}
public List<KpiMessage> fullPoll(int lastSeq) throws Exception {
Statement st = dbConnection.createStatement();
System.out.println("Polling");
ResultSet rs = st.executeQuery("Select * from msg_new_to_bde where ACTION = 804 and SEQ >" +
lastSeq + "order by SEQ DESC");
return pojoCol;
}
Run method for processing:
public void run() {
try {
generate(accumulator.outgoingQueue);
accumulator.manageOutgoing(accumulator.outgoingQueue, dbConnection);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Method for updating into Database
public void updateDb(Collection<KpiMessage> updatedQueue, Connection dbConnection) throws
SQLException{
for(KpiMessage pojoClass : updatedQueue){
Statement stmtupd = dbConnection.createStatement();
System.out.println("Updating");
String query = "UPDATE msg_new_to_bde SET KEYINFO1= 'Processed', KEYINFO2 = 'Updated'
WHERE ACTION = 804";
stmtupd.executeUpdate(query);**My Execution stops here**
Finally an accumulator class for maintaing all these queues:
public boolean isUsed = false;
public synchronized void manageIngoing(List<KpiMessage> list){
if(this.isUsed){
try {
wait();
System.out.println("first wait");
} catch (Exception e1) {
e1.printStackTrace();
}
}
System.out.println("recived pass after update");
this.getIncomingQueue().addAll(list);
//incoming queue copied to outgoing queue
this.setOutgoingQueue(this.getIncomingQueue());
System.out.println("waiting");
System.out.println("new incoming message");
this.isUsed = false;
notifyAll();
}
/**
* Method which handles synchronization using wait and notify for outgoing messages after
polling
* #param outgoingQueue
* #param dbConnection
*/
public synchronized void manageOutgoing(Collection<KpiMessage> outgoingQueue, Connection
dbConnection){
if(!this.isUsed)
{
try {
System.out.println("second wait");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.isUsed = true;
DBhandler dbhandler = new DBhandler();
try {
dbhandler.updateDb(getOutgoingQueue(), dbConnection);
} catch (SQLException e) {
e.printStackTrace();
}
notifyAll();
}
}
My task and Question is :
1.The controller should handle both the threads Poller & processor and accumulator handles the incoming and outgoing queues, finally fed into to updated queue for updating DB after processing
2.My class here just does polling once, is not able to update ,execution stops at
3.Is my wait(), notifyALL() handle correct here.
How to achieve repeated polling and updation here?
Chances are, in this complex setting with five different questions, there will be no complete answer for everything. While waiting for those, you should read up on what java.util.concurrent has to offer, especially the concurrent collections with support for blocking reads and writes. Use wait() and notify() only if the JDK classes are not enough for you.