SimpleChannelUpstreamHandler await*() in I/O thread causes a dead lock - multithreading

In my Netty SimpleChannelUpstreamHandler when I receive a message I need to start up a connection to another Netty Server and forward the message on. However, when starting up this second connection I use:
ChannelFuture channelFuture = clientBootstrap.connect(new InetSocketAddress(host, port));
hannelFuture.awaitUninterruptibly();
Which results in the following error:
java.lang.IllegalStateException: await*() in I/O thread causes a dead lock or sudden performance drop. Use addListener() instead or call await*() from a different thread.
at org.jboss.netty.channel.DefaultChannelFuture.checkDeadLock(DefaultChannelFuture.java:314)
at org.jboss.netty.channel.DefaultChannelFuture.awaitUninterruptibly(DefaultChannelFuture.java:226)
at com.my.NettyClient.start(NettyClient.java:204)
....
at com.my.MyChannelUpstreamHandler.messageReceived(MyChannelUpstreamHandler.java:52)
Whats the best way to start this second connection? Should I do the following?:
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(new Runnable() {
#Override
public void run() {
// Connect to another Netty Server...
// Forward on message...
}
});
executorService.shutdown();
...
Is this wasteful to start a new thread on each message recieved?

Checkout the proxy example to see how you can do it without blocking:
http://netty.io/docs/stable/xref/org/jboss/netty/example/proxy/HexDumpProxyInboundHandler.html

Related

join() waiting forever when exception occurs, jvm shutdown hook not working

I am trying to shutdown the application, whenever any Fatal
Error/Exception comes but before shut down the application my current
thread/task should complete, so I have written mainThread.join()
inside run(), its working fine when there is no exception. But whenever my
doTask() throwing exception that time join() waiting forever.
public class POC
{
public void doTask() throws Exception
{
throw new Exception("Fatal Error");
//throw new Exception("Fatal Error"); By commenting working fine.
}
public static void main(String[] args)
{
POC ob = new POC();
final Thread mainThread = Thread.currentThread();
Runtime.getRuntime().addShutdownHook(new Thread()
{
public void run()
{
try
{
System.out.println("Join() Start");
mainThread.join();
System.out.println("Join() End"); //Why this is not printing?
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
});
try
{
System.out.println("Before doTask()");
ob.doTask(); //User Defined Run()
System.out.println("After doTask()");
}
catch (Exception ex) // FATAL
{
System.err.println("Exception : " + ex.getLocalizedMessage());
System.exit(-1);
}
}
}
OutPut : 0
Before Run()
Exception : Fatal Error
Join() Start
Why System.out.println("Join() End"); is not printing?
You have a simple deadlock.
When you throw an exception, exception handler call System.exit(-1), which is blocking, see javadoc:
Terminates the currently running Java virtual machine by initiating its shutdown sequence
...
The virtual machine's shutdown sequence consists of two phases. In the first phase all registered #addShutdownHook shutdown hooks, if any, are started in some unspecified order and allowed to run concurrently until they finish.
So main thread is waiting in System#exit call until all shutdown hook will be finished and your only shutdown hook blocks and waits until main thread will finish (which is waiting in System#exit ... GOTO 1).

Java EventListener inside of SwingWorker

OK, so I'm a bit new to SwingWorker in Java.
I've built a Java GUI that, when the "Start" button is pressed, launches several SwingWorker threads. The first thread simply keeps track of run time and updates the GUI appropriately. The second one plays a series of sounds files. The third (and problematic) thread should monitor the serial port for incoming data to be manipulated later on down the road. All of these threads will be running for a while, hence them being SwingWorkers.
I am using the jSSC library (https://code.google.com/p/java-simple-serial-connector/wiki/jSSC_examples) to read data from the serial port, and it does so by firing an eventListener.
My question: Is it redundant/inelegant to code an EventListener inside of a SwingWorker thread? And if so, is there a better way to go about this?
Here is a bit of my code:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
SerialPort serialPort = findPort(); // returns a serialport I can use to read data from.
SwingWorker worker1 = new SwingWorker<Void, Void>(){
#Override
protected Void doInBackground() throws Exception {
long elapsedTime, startTime = System.currentTimeMillis();
while (true){
Thread.sleep(1000);
elapsedTime = (System.currentTimeMillis() - startTime)/1000;
jTimeField.setText(String.format("%02d:%02d:%02d", elapsedTime/3600, (elapsedTime%3600)/60, elapsedTime%60));
if (isCancelled()){} /* Check if thread has been canceled */
}
}
};
SwingWorker worker2 = new SwingWorker<Void, Void>(){
#Override
protected Void doInBackground() throws Exception {
// This Thread: Plays music files; Self terminates; On termination also terminates worker 1 and 3 via cancel().
}
};
SwingWorker worker3 = new SwingWorker<Void, Void>(){
#Override
protected Void doInBackground() throws Exception {
serialPort.addEventListener(new SerialPortReader());
return null;
}
class SerialPortReader implements SerialPortEventListener {
#Override
public void serialEvent(SerialPortEvent event) {
byte buffer[];
if (event.isRXCHAR() && event.getEventValue() > 0){
buffer = serialPort.readBytes();
for (byte b: buffer){
// Do stuff with incoming data
}
}
}
}
};
}
Any and all constructive criticism is appreciated.
It does not do any good to add the event listener in your swingworker thread and then return once that's done. Why not just add the listener from your EDT and, if it takes long to process events, fire off processing threads from there? Listening to events can't be blocking, that would defeat the entire Observer pattern.

#Transactional on run() not working

I am using:
org.springframework.orm.hibernate4.HibernateTransactionManager the API of which reads:
Binds a Hibernate Session from the specified factory to the thread,
potentially allowing for one thread-bound Session per factory.
Here is my code under question:
#Transactional
public void insertPerson(Person transientPerson) {
System.out.println("Current session in insert "+sessionFactory.getCurrentSession()); // Line 1
personDao.save(transientPerson);
executeConcurrently();
}
private void executeConcurrently() {
new Thread(new Runnable() {
#Transactional
public void run() {
System.out.println("This is a branew thread "+Thread.currentThread().getName());
System.out.println("In the new thread, session = "+sessionFactory.getCurrentSession()); // Line 2
}
}).start();
}
In line 1 I get the session which is obvious. However line 2's execution shows me this error:
This is a branew thread Thread-2
Exception in thread "Thread-2" org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:978)
at edu.sprhib.service.impl.PersonServiceImpl$1.run(PersonServiceImpl.java:55)
at java.lang.Thread.run(Thread.java:724)
What I fail to understand is why is this failing? According to my understanding, Spring should create a brand new session and associate it with the ThreadLocal of Thread-2. Is my understanding wrong or the code? I am meanwhile trying to debug the Spring code and my netbeans even after attaching source to the spring-orm jar is not being able to debug inside of it (Please note I am not very good at debugging inside framework's code).
Any help will be appreciated.
Thanks in advance,
Mustafa
Try this
#Transactional( propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void insertPerson(Person transientPerson) {
System.out.println("Current session in insert "+sessionFactory.getCurrentSession()); // Line 1
personDao.save(transientPerson);
executeConcurrently();
}
private void executeConcurrently() {
new Thread(new Runnable() {
#Transactional
public void run() {
System.out.println("This is a branew thread "+Thread.currentThread().getName());
System.out.println("In the new thread, session = "+sessionFactory.getCurrentSession()); // Line 2
}
}).start();
}
By using Propagation.REQUIRED Spring Container handle session you don't need to worry about Session object
if your session object destroyed ,container create new one and provide session if we mention our transaction as a propagation = Propagation.REQUIRED

Netty 4 multithreaded DefaultEventExecutorGroup

I started a netty4 nio server with multiple business threads for handling long-term businesses
like below
public void start(int listenPort, final ExecutorService ignore)
throws Exception {
...
bossGroup = new NioEventLoopGroup();
ioGroup = new NioEventLoopGroup();
businessGroup = new DefaultEventExecutorGroup(businessThreads);
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, ioGroup).channel(NioServerSocketChannel.class)
.childOption(ChannelOption.TCP_NODELAY,
Boolean.parseBoolean(System.getProperty(
"nfs.rpc.tcp.nodelay", "true")))
.childOption(ChannelOption.SO_REUSEADDR,
Boolean.parseBoolean(System.getProperty(
"nfs.rpc.tcp.reuseaddress", "true")))
.childHandler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch)
throws Exception {
ch.pipeline().addLast("decoder",
new Netty4ProtocolDecoder());
ch.pipeline().addLast("encoder",
new Netty4ProtocolEncoder());
ch.pipeline().addLast(businessGroup, "handler",
new Netty4ServerHandler());
}
});
b.bind(listenPort).sync();
LOGGER.warn("Server started,listen at: " + listenPort + ", businessThreads is " + businessThreads);
}
I found that there was only one thread working when the server accepted one connection.
How can I bootstrap a server that can start multiple business threads for only one connection?
Thanks,
Mins
Netty will always use the same thread for one connection. It's by design. If you would like to change this you may be able to implement a custom EventExecutorGroup and pass it in when adding your ChannelHandler to the ChannelPipeline.
Be aware this may result in messed up order of packets.

Netty OrderedMemoryAwareThreadPoolExecutor not creating multiple threads

I use Netty for a multithreaded TCP server and a single client persistent connection.
The client sends many binary messages (10000 in my use case) and is supposed to receive an answer for each message. I added an OrderedMemoryAwareThreadPoolExecutor to the pipeline to handle the execution of DB calls on multiple threads.
If I run a DB call in the method messageReceived() (or simulate it with Thread.currentThread().sleep(50)) then all events are handled by a single thread.
5 count of {main}
1 count of {New
10000 count of {pool-3-thread-4}
For a simple implementation of messageReceived() the server creates many executor threads as expected.
How should I configure the ExecutionHandler to get multiple threads executors for the business logic, please?
Here is my code:
public class MyServer {
public void run() {
OrderedMemoryAwareThreadPoolExecutor eventExecutor = new OrderedMemoryAwareThreadPoolExecutor(16, 1048576L, 1048576L, 1000, TimeUnit.MILLISECONDS, Executors.defaultThreadFactory());
ExecutionHandler executionHandler = new ExecutionHandler(eventExecutor);
bootstrap.setPipelineFactory(new ServerChannelPipelineFactory(executionHandler));
}
}
public class ServerChannelPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
pipeline.addLast("encoder", new MyProtocolEncoder());
pipeline.addLast("decoder", new MyProtocolDecoder());
pipeline.addLast("executor", executionHandler);
pipeline.addLast("myHandler", new MyServerHandler(dataSource));
}
}
public class MyServerHandler extends SimpleChannelHandler {
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) throws DBException {
// long running DB call simulation
try {
Thread.currentThread().sleep(50);
} catch (InterruptedException ex) {
}
// a simple message
final MyMessage answerMsg = new MyMessage();
if (e.getChannel().isWritable()) {
e.getChannel().write(answerMsg);
}
}
}
OrderedMemoryAwareThreadPoolExecutor guarantees that events from a single channel are processed in order. You can think of it as binding a channel to a specific thread in the pool and then processing all events on that thread - although it's a bit more complex than that, so don't depend on a channel always being processed by the same thread.
If you start up a second client you'll see it (most likely) being processed on another thread from the pool. If you really can process a single client's requests in parallel then you probably want MemoryAwareThreadPoolExecutor but be aware that this offers no guarantees on the order of channel events.

Resources