我有一个程序,可以收听博士后的活动。应用程序已被证实,工作正常。问题是,当我从服务器上删除应用程序时,我可以看到catalina文件中的日志。看起来线程仍然在后台运行。我该如何停止线程运行。
Catalina 的原木有:
03-Sep-2020 15:41:46.025 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.startup.HostConfig.undeploy Undeploying context [/msms]
03-Sep-2020 15:41:46.035 WARNING [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [msms] registered the JDBC driver [com.impossibl.postgres.jdbc.PGDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
03-Sep-2020 15:41:46.036 WARNING [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [msms] appears to have started a thread named [PG-JDBC Housekeeper] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
com.impossibl.postgres.jdbc.ThreadedHousekeeper$1.run(ThreadedHousekeeper.java:187)
03-Sep-2020 15:41:46.036 WARNING [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [msms] appears to have started a thread named [PG-JDBC I/O (1)] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
io.netty.channel.epoll.Native.epollWait(Native Method)
io.netty.channel.epoll.Native.epollWait(Native.java:148)
io.netty.channel.epoll.Native.epollWait(Native.java:141)
io.netty.channel.epoll.EpollEventLoop.epollWaitNoTimerChange(EpollEventLoop.java:290)
io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:347)
io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
java.lang.Thread.run(Thread.java:745)
03-Sep-2020 15:41:46.037 SEVERE [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [msms] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@24002836]) and a value of type [io.netty.util.internal.InternalThreadLocalMap] (value [io.netty.util.internal.InternalThreadLocalMap@24e9076e]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
使用以下代码。
/**
* This program uses the pgjdbc_ng driver which has an asynchronous
* implementation for blocking on the Postgres NOTIFY/LISTEN events.
*
* No polling is done using this driver. You will see a forever loop
* "while(true)" in the main(). This is done to keep the program running and
* listening to multiple events happening in Postgres. Normally you would just
* take one event and then do something with it.
*
*/
public class ListenNotify {
// Create the queue that will be shared by the producer and consumer
private BlockingQueue queue = new ArrayBlockingQueue(10);
// Database connection
PGConnection connection;
public ListenNotify() {
// Get database info from environment variables
String DBHost = System.getenv("DBHost");
String DBName = System.getenv("DBName");
String DBUserName = System.getenv("DBUserName");
String DBPassword = System.getenv("DBPassword");
// Create the listener callback
PGNotificationListener listener = new PGNotificationListener() {
@Override
public void notification(int processId, String channelName, String payload) {
// Add event and payload to the queue
queue.add("/channels/" + channelName + " " + payload);
System.out.println("*********INSIDE NOTIFICATION*************");
System.out.println("notification = " + payload);
Advocate advocate = ParseJSON.parseJSON(payload);
String sent=advocate.getSent();
String date=advocate.getDate();
String mobile = advocate.getMobile();
String message = advocate.getMessage();
System.out.println("sent::" + sent);
System.out.println("message::" + message);
System.out.println("mobile::" + mobile);
System.out.println("date::" + date);
sendSMS sendSMS = new sendSMS();
Integer ack = sendSMS.sendSMS(mobile, message);
System.out.println("ack::" + ack);
}
};
try {
// Create a data source for logging into the db
PGDataSource dataSource = new PGDataSource();
dataSource.setHost("172.16.2.32");
dataSource.setPort(5432);
dataSource.setDatabaseName("smsdb");
dataSource.setUser("postgres");
dataSource.setPassword("postgres");
// Log into the db
connection = (PGConnection) dataSource.getConnection();
// add the callback listener created earlier to the connection
connection.addNotificationListener(listener);
// Tell Postgres to send NOTIFY q_event to our connection and listener
Statement statement = connection.createStatement();
DatabaseMetaData dbmd = connection.getMetaData();
try (ResultSet tables = dbmd.getTables(null, null, "%", new String[] { "TABLE" })) {
while (tables.next()) {
System.out.println(tables.getString("TABLE_NAME"));
}
}
statement.execute("LISTEN q_event");
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* @return shared queue
*/
public BlockingQueue getQueue() {
return queue;
}
/**
*
* main entry point
*
* @param args
*/
public static void main(String[] args) {
// Create a new listener
ListenNotify ln = new ListenNotify();
// Get the shared queue
BlockingQueue queue = ln.getQueue();
// Loop forever pulling messages off the queue
while (true) {
try {
// queue blocks until something is placed on it
String msg = (String) queue.take();
// Do something with the event
System.out.println(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
甚至这个类也不会取消注册驱动程序,而且这种方法(在上下文侦听器中强制取消注册)的更多问题是一些驱动程序保持内部注册状态。这意味着,当监听器将驱动程序从drivermanager中删除时,其内部状态认为它仍在注册中。这反过来意味着它在重新加载时将无法重新注册。哎哟!
h2和postgresql是两个类似的驱动程序(链接指向相关的源代码行)。
mywebappcontextlistener.java文件
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
public class MyWebAppContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("**************Starting up!**************");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("**************Shutting down!**************");
System.out.println("Destroying Context...");
// ... First close any background tasks which may be using the DB ...
// ... Then close any DB connection pools ...
// Now deregister JDBC drivers in this context's ClassLoader:
// Get the webapp's ClassLoader
ClassLoader cl = Thread.currentThread().getContextClassLoader();
// Loop through all drivers
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (driver.getClass().getClassLoader() == cl) {
try {
System.out.println("Deregistering JDBC driver {}");
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
System.out.println("Error deregistering JDBC driver {}");
ex.printStackTrace();
}
} else {
// driver was not registered by the webapp's ClassLoader and may be in use elsewhere
System.out
.println("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader");
}
}
}
}
暂无答案!
目前还没有任何答案,快来回答吧!