All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.netty.util.VirtualExecutorService Maven / Gradle / Ivy

Go to download

The Netty project is an effort to provide an asynchronous event-driven network application framework and tools for rapid development of maintainable high performance and high scalability protocol servers and clients. In other words, Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server.

There is a newer version: 4.0.0.Alpha8
Show newest version
/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package org.jboss.netty.util;

import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;

import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;


/**
 * A delegating {@link ExecutorService} with its own termination management.
 * 

* {@link VirtualExecutorService} is used when you want to inject an * {@link ExecutorService} but you do not want to allow the explicit termination * of threads on shutdown request. It is particularly useful when the * {@link ExecutorService} to inject is shared by different components and * the life cycle of the components depend on the termination of the injected * {@link ExecutorService}. * *

 * ExecutorService globalExecutor = ...;
 * ExecutorService virtualExecutor = new {@link VirtualExecutorService}(globalExecutor);
 *
 * {@link ChannelFactory} factory =
 *         new {@link NioServerSocketChannelFactory}(virtualExecutor, virtualExecutor);
 * ...
 *
 * // ChannelFactory.releaseExternalResources() shuts down the executor and
 * // interrupts the I/O threads to terminate all I/O tasks and to release all
 * // resources acquired by ChannelFactory.
 * factory.releaseExternalResources();
 *
 * // Note that globalExecutor is not shut down because VirtualExecutorService
 * // implements its own termination management. All threads which were acquired
 * // by ChannelFactory via VirtualExecutorService are returned to the pool.
 * assert !globalExecutor.isShutdown();
 * 
* *

The differences from an ordinary {@link ExecutorService}

* * A shutdown request ({@link #shutdown()} or {@link #shutdownNow()}) does not * shut down its parent {@link Executor} but simply sets its internal flag to * reject further execution request. *

* {@link #shutdownNow()} interrupts only the thread which is executing the * task executed via {@link VirtualExecutorService}. *

* {@link #awaitTermination(long, TimeUnit)} does not wait for real thread * termination but wait until {@link VirtualExecutorService} is shut down and * its active tasks are finished and the threads are returned to the parent * {@link Executor}. * @apiviz.landmark */ public class VirtualExecutorService extends AbstractExecutorService { private final Executor e; private final ExecutorService s; final Object startStopLock = new Object(); volatile boolean shutdown; Set activeThreads = new MapBackedSet(new IdentityHashMap()); /** * Creates a new instance with the specified parent {@link Executor}. */ public VirtualExecutorService(Executor parent) { if (parent == null) { throw new NullPointerException("parent"); } if (parent instanceof ExecutorService) { e = null; s = (ExecutorService) parent; } else { e = parent; s = null; } } public boolean isShutdown() { synchronized (startStopLock) { return shutdown; } } public boolean isTerminated() { synchronized (startStopLock) { return shutdown && activeThreads.isEmpty(); } } public void shutdown() { synchronized (startStopLock) { if (shutdown) { return; } shutdown = true; } } public List shutdownNow() { synchronized (startStopLock) { if (!isTerminated()) { shutdown(); for (Thread t: activeThreads) { t.interrupt(); } } } return Collections.emptyList(); } public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { synchronized (startStopLock) { while (!isTerminated()) { startStopLock.wait(TimeUnit.MILLISECONDS.convert(timeout, unit)); } return isTerminated(); } } public void execute(Runnable command) { if (command == null) { throw new NullPointerException("command"); } if (shutdown) { throw new RejectedExecutionException(); } if (s != null) { s.execute(new ChildExecutorRunnable(command)); } else { e.execute(new ChildExecutorRunnable(command)); } } private class ChildExecutorRunnable implements Runnable { private final Runnable runnable; ChildExecutorRunnable(Runnable runnable) { this.runnable = runnable; } public void run() { Thread thread = Thread.currentThread(); synchronized (startStopLock) { activeThreads.add(thread); } try { runnable.run(); } finally { synchronized (startStopLock) { boolean removed = activeThreads.remove(thread); assert removed; if (isTerminated()) { startStopLock.notifyAll(); } } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy