java nio InterruptibleChannel,AbstractInterruptibleChannel源码分析

目录

InterruptibleChannel

AbstractInterruptibleChannel


InterruptibleChannel


package java.nio.channels;

import java.io.IOException;


/**
 * 可以异步关闭和中断的通道。
 *
 * <p> 实现此接口的通道是异步关闭的:
 * 如果一个线程在可中断通道上的I/O操作中被阻塞,
 * 那么另一个线程可能会调用该通道的关闭方法。
 * 这将导致阻塞的线程接收一个AsynchronousCloseException异常。
 *
 * <p> 实现此接口的通道也是可中断的:
 * 如果一个线程在可中断通道上的I/O操作中被阻塞,那么另一个线程可能会调用被阻塞线程的interrupt方法。
 * 这将导致通道被关闭,阻塞线程接收一个ClosedByInterruptException异常,并且阻塞线程的中断状态被设置。
 *
 * <p> 如果一个线程的中断状态已经设置,它调用一个阻塞的I/O操作,然后通道将被关闭,
 * 线程将立即收到一个ClosedByInterruptException;
 * 它的中断状态将保持设置。
 *
 * <p> 通道在(且仅在)实现此接口时支持异步关闭和中断。
 * 如果有必要,可以在运行时通过instanceof操作符进行测试。
 *
 *
 * @author Mark Reinhold
 * @author JSR-51 Expert Group
 * @since 1.4
 */

public interface InterruptibleChannel
    extends Channel
{

    /**
     * 关闭这个通道。
     *
     * <p> 当前在此通道上的I/O操作中阻塞的任何线程都将接收到一个AsynchronousCloseException异常。
     *
     * <p> 否则,此方法的行为将与Channel接口所指定的完全相同。</p>
     *
     * @throws  IOException  If an I/O error occurs
     */
    public void close() throws IOException;

}

AbstractInterruptibleChannel


package java.nio.channels.spi;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.nio.channels.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.nio.ch.Interruptible;


/**
 * 可中断通道的基本实现类。
 *
 * <p> 这个类封装了实现通道的异步关闭和中断所需的底层机制。
 * 具体的通道类必须分别在调用可能阻塞的I/O操作之前和之后调用begin和end方法。
 * 为了确保end方法总是被调用,这些方法应该在try中使用。finally块:
 *
 * <blockquote><pre>
 * boolean completed = false;
 * try {
 *     begin();
 *     completed = ...;    // Perform blocking I/O operation
 *     return ...;         // Return result
 * } finally {
 *     end(completed);
 * }</pre></blockquote>
 *
 * <p> end方法的已完成参数说明I/O操作是否实际完成,也就是说,它是否对调用程序有任何可见的效果。
 * 例如,在一个读取字节的操作的情况下,这个参数应该是真的,
 * 如果,并且仅当,一些字节实际上被转移到调用者的目标缓冲区。
 *
 * <p> 具体的channel类还必须实现implCloseChannel方法,
 * 如果它被调用,而另一个线程在本地I/O操作中被阻塞,那么该操作将立即返回,要么抛出异常,要么正常返回。
 * 如果线程被中断,或者阻塞线程的通道被异步关闭,那么通道的end方法将抛出相应的异常。
 *
 * <p>这个类执行实现Channel所需的同步规范。
 * implCloseChannel方法的实现不需要与可能试图关闭通道的其他线程同步。</p>
 *
 *
 * @author Mark Reinhold
 * @author JSR-51 Expert Group
 * @since 1.4
 */

public abstract class AbstractInterruptibleChannel
    implements Channel, InterruptibleChannel
{

    private final Object closeLock = new Object();
    private volatile boolean open = true;

    /**
     * 初始化此类的新实例
     */
    protected AbstractInterruptibleChannel() { }

    /**
     * 关闭这个通道。
     *
     * <p> 如果通道已经关闭,则此方法立即返回。
     *  否则,它将通道标记为closed,然后调用implCloseChannel方法来完成close操作。</p>
     *
     * @throws  IOException
     *          If an I/O error occurs
     */
    public final void close() throws IOException {
        synchronized (closeLock) {
            if (!open)
                return;
            open = false;
            implCloseChannel();
        }
    }

    /**
     * 关闭这个通道。
     *
     * <p> 该方法由close方法调用,以执行关闭通道的实际工作。
     * 只有在通道尚未关闭的情况下才会调用此方法,并且只调用一次。
     *
     * <p> 此方法的实现必须安排,在此通道上的I/O操作中阻塞的任何其他线程,将立即返回,
     * 可以通过抛出异常,也可以通过正常返回。
     * </p>
     *
     * @throws  IOException
     *          If an I/O error occurs while closing the channel
     */
    protected abstract void implCloseChannel() throws IOException;

    public final boolean isOpen() {
        return open;
    }


    // -- Interruption 机制 --

    private Interruptible interruptor;
    private volatile Thread interrupted;

    /**
     * 标记可能无限期阻塞的I/O操作的开始。
     *
     * <p> 该方法应该与end方法一起调用,使用try…finally,
     * 阻塞如上所示,以实现该通道的异步丢失和中断。</p>
     */
    protected final void begin() {
        if (interruptor == null) {
        	// interruptor 单例模式,设置一个interruptor
            interruptor = new Interruptible() {
            		// target是导致其他线程interrupt的线程
                    public void interrupt(Thread target) {
                        synchronized (closeLock) {
                            if (!open)
                                return;
                            // 对通道执行关闭操作,设置interrupted
                            open = false;
                            interrupted = target;
                            try {
                                AbstractInterruptibleChannel.this.implCloseChannel();
                            } catch (IOException x) { }
                        }
                    }};
        }
        // 会在interruptor上阻塞
        blockedOn(interruptor);
        Thread me = Thread.currentThread();
        // 如果当前线程已经是Interrupted,调用interruptor.interrupt(me)
        if (me.isInterrupted())
            interruptor.interrupt(me);
    }

    /**
     * 标记可能无限期阻塞的I/O操作的结束。
     *
     * <p> 该方法应该与begin方法一起调用,使用try…finally,如上所示的区块,以实现该通道的异步丢失和中断。
     *
     * @param  completed
     *         <tt>true</tt> if, and only if, the I/O operation completed
     *         successfully, that is, had some effect that would be visible to
     *         the operation's invoker
     *
     * @throws  AsynchronousCloseException
     *          If the channel was asynchronously closed
     *
     * @throws  ClosedByInterruptException
     *          If the thread blocked in the I/O operation was interrupted
     */
    protected final void end(boolean completed)
        throws AsynchronousCloseException
    {
    	// 清空阻塞的东西(原来是interruptor)
        blockedOn(null);
        Thread interrupted = this.interrupted;
        // 如果interrupted不为null,而且是线程自己,清空interrupted,抛出ClosedByInterruptException
        if (interrupted != null && interrupted == Thread.currentThread()) {
            interrupted = null;
            throw new ClosedByInterruptException();
        }
        // 如果IO操作未完成,并且通道已关闭,抛出AsynchronousCloseException
        if (!completed && !open)
            throw new AsynchronousCloseException();
    }


    // -- sun.misc.SharedSecrets --
    static void blockedOn(Interruptible intr) {         // package-private
        sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(),
                                                             intr);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值