`
coolxing
  • 浏览: 874182 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
9a45b66b-c585-3a35-8680-2e466b75e3f8
Java Concurre...
浏览量:97285
社区版块
存档分类
最新评论

处理不可中断的阻塞-JCIP7.1读书笔记

阅读更多

[本文是我对Java Concurrency In Practice 7.1的归纳和总结.  转载请注明作者和出处,  如有谬误, 欢迎在评论中指正. ]

并不是所有的阻塞都是可中断的, 比如InputStream.read方法. 在检测到输入数据可用, 到达流末尾或者抛出异常前, 该方法一直阻塞. 而且阻塞的时候不会检查中断标记, 所以中断线程无法使read从阻塞状态返回. 但是关闭流可以使得read方法抛出异常, 从而从阻塞状态返回. 

public class ReaderThread extends Thread {
	private static final int BUFSZ = 1024;
	private final Socket socket;
	private final InputStream in;

	public ReaderThread(Socket socket) throws IOException {
		this.socket = socket;
		this.in = socket.getInputStream();
	}

	// 覆盖Thread类的interrupt方法, 加入关闭socket的代码
	// 如果发生中断时, 线程阻塞在read方法上, socket的关闭会导致read方法抛出SocketException, 然后run方法运行完毕
	public void interrupt() {
		try {
			socket.close();
		} catch (IOException ignored) {
		} finally {
			super.interrupt();
		}
	}

	public void run() {
		try {
			byte[] buf = new byte[BUFSZ];
			while (true) {
				int count = in.read(buf);
				if (count < 0)
					break;
				else if (count > 0)
					processBuffer(buf, count);
			}
		} catch (IOException e) { /*  Allow thread to exit  */
		}
	}

	private void processBuffer(byte[] buf, int count) {
		//...
	}
}

如果task并非在自己创建的线程里运行, 而是提交给线程池运行的话, 就无法使用上例的方式处理不可中断阻塞了. 之前有过分析, 对于提交给线程池执行的task, 应该通过Future.cancel方法提前终止task的运行, 所以可以考虑重写Future.cancel方法, 在其中加入关闭socket的操作. Future对象是由submit方法返回的, 其源代码如下:

public <T> Future<T> submit(Callable<T> task) {
	if (task == null) 
		throw new NullPointerException();
	RunnableFuture<T> ftask = newTaskFor(task);
	execute(ftask);
	return ftask;
} 

可知submit方法返回的Future对象是调用newTaskFor方法获得的:

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
	return new FutureTask<T>(callable);
} 

newTaskFor方法被声明为protected, 所以我们可以通过继承覆盖该方法, 返回自定义的Future对象.

首先将需要覆盖的2个方法定义在接口中:

public interface CancellableTask<T> extends Callable<T> { 
	void cancel(); 
	RunnableFuture<T> newTask(); 
}  

然后让task类实现CancellableTask接口:

public abstract class SocketUsingTask<T> implements CancellableTask<T> {
	private Socket socket;

	protected synchronized void setSocket(Socket s) {
		socket = s;
	}

	public synchronized void cancel() {
		try {
			if (socket != null)
				socket.close();
		} catch (IOException ignored) {
		}
	}

	public RunnableFuture<T> newTask() {
		return new FutureTask<T>(this) {
			// 定义FutureTask的匿名内部类, 并覆盖cancel方法, 向其中加入关闭socket的操作
			public boolean cancel(boolean mayInterruptIfRunning) {
				try {
					SocketUsingTask.this.cancel();
				} finally {
					return super.cancel(mayInterruptIfRunning);
				}
			}
		};
	}
}

接着继承ThreadPoolExecutor类并覆盖newTaskFor方法, 让该方法返回自定义的FutureTask对象:

public class CancellingExecutor extends ThreadPoolExecutor {
	// ...
	protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
		// 如果callable是CancellableTask对象, 那么就返回自定义的FutureTask(通过调用其newTaskFor方法实现)
		if (callable instanceof CancellableTask)
			return ((CancellableTask<T>) callable).newTask();
		else
			return super.newTaskFor(callable);
	}
}

测试代码:

public static void main(String[] args) {
	CancellingExecutor executor = new CancellingExecutor();
	SocketUsingTask task = new SocketUsingTask();
	task.setSocket(new Socket("www.baidu.com", 80));
	Future<V> future = executor.submit(task);
	future.cancel(true);
}
1
1
分享到:
评论

相关推荐

    i2active_node-7.1

    在i2active_node-7.1项目中,我们可以预期它会利用Node.js的事件驱动模型来处理并发请求,通过监听和响应事件来实现非阻塞I/O操作。这种模式对于处理大量并发连接非常有效,尤其适合构建高并发的实时应用,如聊天...

    内核中断处理-内核中断处理

    底半部(Delayed Work)机制则用于将耗时较长的任务从ISR中分离出来,避免阻塞中断处理。 中断处理的数据结构,如中断描述符表(Interrupt Descriptor Table, IDT)和中断处理程序指针,是用来管理和定位中断处理代码的...

    Linux设备驱动程序学习(11)-中断处理 - Linux设备驱动程序

    在Linux设备驱动程序中,中断处理是不可或缺的部分,因为它允许设备在非阻塞状态下执行任务,提高系统的并行性和效率。 1. **中断概述**:中断分为硬件中断和服务请求(Software Interrupts, SoftIRQs)。硬件中断...

    linux中断--中断嵌套&中断请求丢失.docx

    《Linux中断:中断嵌套...然而,正确地设计和实现中断处理程序,避免长时间阻塞中断,是确保系统稳定运行的关键。在编写驱动程序时,需要充分理解这些概念,并合理地利用内核提供的机制,以保证中断处理的高效和准确。

    linux中断--内核中断编程.docx

    同时,中断处理函数的编写必须高效且避免阻塞,因为中断处理是上下文切换的关键点,影响系统的实时性。 此外,中断处理还可以涉及中断共享、中断底半部(SoftIRQs)和任务队列(Tasklets)等概念,这些在更复杂的...

    Python库 | aiotrello-0.0.7.1-py3-none-any.whl

    1. **异步操作**:aiotrello库基于Python的asyncio库构建,支持非阻塞I/O,这意味着它能够在等待网络操作时执行其他任务,提高了程序的效率和响应速度。 2. **Trello API封装**:该库提供了对Trello API的全面封装...

    mini2440-128M开发板裸奔系列——外部中断EINT8-23 六按键中断

    这个话题对于嵌入式系统开发者来说是至关重要的,因为它涉及到硬件中断处理,这是实时系统中不可或缺的一部分。 首先,Mini2440是一款基于S3C2440 ARM9处理器的开发板,具有128MB内存,广泛用于嵌入式系统的学习和...

    station-official-web.zip

    1. **事件驱动**:Node.js基于Chrome V8引擎,采用事件驱动、非阻塞I/O模型,使其在处理高并发请求时表现出色。 2. **单线程与异步编程**:Node.js的主要工作方式是异步编程,避免了线程上下文切换的开销,提升了...

    微信小程序-图书馆写笔记源码.zip

    "微信小程序-图书馆写笔记源码.zip" 是一个包含构建微信小程序的源代码文件的压缩包,专门用于创建一个图书馆笔记功能的小程序。 在微信小程序的开发过程中,主要涉及以下几个核心知识点: 1. **微信开发者工具**...

    串口收发数据-中断-C语言代码.rar

    - **避免死锁**:确保中断服务程序不会长时间运行,防止阻塞其他中断。 - **同步问题**:中断处理时要防止数据竞争,可能需要使用锁或信号量来保护共享资源。 - **中断优先级**:合理设置中断优先级,保证高...

    Android代码-局域网简易云端笔记系统源码.zip

    对于触摸事件处理、界面动态更新等方面的知识也是必不可少的。 8. **权限管理**:在Android中,访问网络和读写存储都需要用户的权限。因此,源码中可能包含了请求这些权限的代码。 9. **版本控制**:由于这是一个...

    LPC1768中断1,中断2

    - ISR应该尽可能简洁,避免长时间阻塞其他中断。 - 在ISR中,通常需要保存和恢复CPU的状态,以防止中断嵌套时的混乱。 - 完成处理后,通常会清除中断标志,以防重复触发中断。 5. **中断程序的实现步骤** - **...

    多核微处理器系统中断处理和中断控制的实现

    非阻塞中断不等待当前指令执行完毕就能立即响应,常用于处理紧急情况。快速中断则提供了更高效的中断处理路径,适用于需要快速响应的场合。 8. 中断虚拟化: 在虚拟化环境中,虚拟机监控器(VMM)需要模拟中断处理...

    CocoaAsyncSocket-7.1

    队列的非阻塞的读和写,而且可选超时。你可以调用它读取和写入,它会当完成后告知你 自动的socket接收。如果你调用它接收连接,它将为每个连接启动新的实例,当然,也可以立即关闭这些连接 委托(delegate)支持。...

    RT-Thread学习笔记(1)- 内核移植 - 代码

    3. **中断处理**:RT-Thread提供了中断管理框架,需要根据目标硬件实现中断向量表和中断处理函数。中断服务例程应遵循RTOS的规则,避免长时间阻塞调度。 4. **内存管理**:RTOS内核需要一个内存管理系统,用于动态...

    swoole-loader72.SO组件下载

    这种模式在处理大量并发连接时非常高效,因为系统可以同时处理多个请求,而不需要为每个请求分配独立的线程或进程。 协程是Swoole中的另一个关键概念。不同于线程或进程,协程是一种轻量级的并发机制,它们在同一...

    Stm32中断优先级相关概念与使用笔记 20181125

    在实际应用中,要确保中断服务例程的简洁高效,避免长时间运行的任务,防止阻塞其他中断。此外,对于可能引发数据竞争的共享资源,应使用互斥锁或信号量等机制来保护。 10. 示例应用: 例如,在实时控制系统中,...

    linux内核中断实例

    - 在中断处理过程中,CPU处于中断上下文,这意味着不能调度其他进程,也不能执行阻塞操作。 - 因此,中断处理程序必须保持轻量级,快速完成任务。 7. **中断异常与错误处理** - 如果在中断处理过程中出现错误,...

    OMAP-L138的新历程之DSP6748中断intc

    中断是实时系统中不可或缺的一部分,它允许处理器在执行正常任务的同时响应外部事件。 C6748 DSP的中断控制模块提供四种类型的中断信号: 1. 一个可屏蔽的硬件异常(EXCEP) 2. 十二个可屏蔽硬件中断(INT4到INT15...

Global site tag (gtag.js) - Google Analytics