返回顶部
首页 > 资讯 > 精选 >Java阻塞的处理方式是怎样的
  • 905
分享到

Java阻塞的处理方式是怎样的

2023-06-17 11:06:33 905人浏览 八月长安
摘要

这篇文章主要介绍了Java阻塞的处理方式是怎样的的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java阻塞的处理方式是怎样的文章都会有所收获,下面我们一起来看看吧。在Java1.4以前,Java的网络编程是只有

这篇文章主要介绍了Java阻塞的处理方式是怎样的的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java阻塞的处理方式是怎样的文章都会有所收获,下面我们一起来看看吧。

在Java1.4以前,Java的网络编程是只有阻塞方式的,在Java1.4以及之后,Java提供了非阻塞的网络编程api.从Java的发展来看,由于Java的快速发展,JVM性能的提升,涉足到服务端应用程序开发也越来越多,要求高性能的网络应用越来越多,这是Java推出非阻塞网络编程的最主要原因吧。

在阻塞的网络编程方式中,针对于每一个单独的网络连接,都必须有一个线程对应的绑定该网络连接,进行网络字节流的处理。下面是一段代码:

public static void main(String[] args) {  try {  ServerSocket ssc = new ServerSocket(23456);  while (true) {  System.out.println("Enter Accept:");  Socket s = ssc.accept();  try {  (new Thread(new Worker(s))).start();  } catch (Exception e) {  // TODO  e.printStackTrace();  }  }  } catch (IOException e) {  e.printStackTrace();  }    }    public static class Worker implements Runnable {  private Socket s;    private boolean running = true;;    public Worker(Socket s) {  this.s = s;  }    public void run() {  try {  InputStream is = s.getInputStream();  OutputStream os = s.getOutputStream();  while (running) {  byte[] b = this.readByLength(is, 1024);  this.process(b);  }  } catch (Throwable t) {  // TODO  t.printStackTrace();  }  }    private byte[] readByLength(InputStream is, int contLen) throws IOException {  byte[] b = new byte[contLen];  int off = 0;  int length = 0;  while ((length = is.read(b, off, contLen - off)) >= 0) {  off = +length;  if (off >= contLen) {  break;  }  }  return b;  }    private void process(byte[] b) {    }  }

在这段代码中,我们看到有两个阻塞的方法,是ServerSocket的accept()方法;和InputStream的read()方式。因此我们需要两类型的线程分别进行处理。而且每一个阻塞方法所绑定的线程的生命周期和网络连接的生命周期是一致的。基于以上的原因,NIO应运而生,一方面,为每一个网络连接建立一个线程对应,同时每一个线程有大量的线程处于读写以外的空闲状态,因此希望降低线程的数量,降低每个空闲状态,提高单个线程的运行执行效率,实际上是在更加充分运用CPU的计算、运行能力(因为,如果有大量的链路存在,就存在大量的线程,而大量的线程都阻塞在read()或者write()方法,同时CPU又需要来回频繁的在这些线程中间调度和切换,必然带来大量的系统调用和资源竞争.);另外一方面希望提高网络IO和硬盘IO操作的性能。在NIO主要出现了三个新特性:

数据缓冲处理(ByteBuffer):由于操作系统和应用程序数据通信的原始类型是byte,也是IO数据操作的基本单元,在NIO中,每一个基本的原生类型(boolean除外)都有Buffer的实现:CharBuffer、IntBuffer、DoubleBuffer、ShortBuffer、LongBuffer、FloatBuffer和ByteBuffer,数据缓冲使得在IO操作中能够连续的处理数据流。当前有两种ByteBuffer,一种是Direct ByteBuffer,另外一种是NonDirect ByteBuffer;ByteBuffer是普通的Java对象,遵循Java堆中对象存在的规则;而Direct ByteBuffer是native代码,它内存的分配不在Java的堆栈中,不受Java内存回收的影响,每一个Direct ByteBuffer都是直接分配的一块连续的内存空间,也是NIO提高性能的重要办法之一。另外数据缓冲有一个很重要的特点是,基于一个数据缓冲可以建立一个或者多个逻辑的视图缓冲(View Buffer).比方说,通过View Buffer,可以将一个Byte类型的Buffer换作Int类型的缓冲;或者一个大的缓冲转作很多小的Buffer。之所以称为View Buffer是因为这个转换仅仅是逻辑上,在物理上并没有创建新的Buffer。这为我们操作Buffer带来诸多方便。

异步通道(Channel):Channel是一个与操作系统紧密结合的本地代码较多的对象。通过Channel来实现网络编程的非阻塞操作,同时也是其与ByteBuffer、Socket有效结合充分利用非阻塞、ByteBuffer的特性的。在后面我们会看到具体的SocketChannel的用法。

有条件的选择(Readiness Selection):大多数操作系统都有支持有条件选择准备就绪IO通道的API,即能够保证一个线程同时有效管理多个IO通道。在NIO中,由Selector(维护注册进来的Channel和这些Channel的状态)、SelectableChannel(能被Selector管理的Channel)和SelectionKey(SelectionKey标识Selector和SelectableChannel之间的映射关系,一旦一个Channel注册到Selector中,就会返回一个SelectionKey对象。SelectionKey保存了两类状态:对应的Channel注册了哪些操作;对应的Channel的那些操作已经准备好了,可以进行相应的数据操作了)结合来实现这个功能的。

NIO的包中主要包含了这样几种抽象数据类型:

◆  Buffer:包含数据且用于读写的线形表结构。其中还提供了一个特殊类用于内存映射文件的I/O操作。

◆ Charset:它提供Unicode字符串影射到字节序列以及逆映射的操作。

◆ Channels:包含socket,file和pipe三种管道,都是全双工的通道。

◆ Selector:多个异步I/O操作集中到一个或多个线程中(可以被看成是Unix中select()函数的面向对象版本)。

NIO非阻塞的典型编程模型如下:

private Selector selector = null;  private static final int BUF_LENGTH = 1024;  public void start() throws IOException {  if (selector != null) {  selector = Selector.open();  }  ServerSocketChannel ssc = ServerSocketChannel.open();  ServerSocket serverSocket = ssc.socket();  serverSocket.bind(new InetSocketAddress(80));  ssc.configureBlocking(false);  ssc.reGISter(selector, SelectionKey.OP_ACCEPT);  try {  while (true) {  int nKeys = UnblockServer.this.selector.select();  if (nKeys > 0) {  Iterator it = selector.selectedKeys().iterator();  while (it.hasNext()) {  SelectionKey key = (SelectionKey) it.next();  if (key.isAcceptable()) {  ServerSocketChannel server = (ServerSocketChannel) key.channel();  SocketChannel channel = server.accept();  if (channel == null) {  continue;  }  channel.configureBlocking(false);  channel.register(selector, SelectionKey.OP_READ);  }  if (key.isReadable()) {  readDataFromSocket(key);  }  it.remove();  }  }  }  } catch (IOException ioe) {  ioe.printStackTrace();  }  }   private void readDataFromSocket(SelectionKey key) throws IOException {  ByteBuffer buf = ByteBuffer.allocate(BUF_LENGTH);  SocketChannel sc = (SocketChannel) key.channel();  int readBytes = 0;  int ret;  try {  while ((ret = sc.read(buf.buf())) > 0) {  readBytes += ret;  }  } finally {  buf.flip();  }  // process buffer  // buf.clear();  }

从这段程序,我们基本可以了解到NIO网络编程的一些特点,创建一个SocketServer的方式已经发生了变化,需要指定非阻塞模式,需要创建一个Channel然后注册到Selector中去,同样,建立一个网络连接过程也是一样的模式,然后就是有条件的选择(Readiness Selection).这样,我们的每一个线程只需要处理一类型的网络选择。在代码上,我们发现处理的方式和阻塞完全不一样了,我们需要完全重新考虑如何编写网络通信的模块了:

持久连接的超时问题(Timeout),因为API没有直接的支持timeout的参数设置功能,因此需要我们自己实现一个这样功能。

如何使用Selector,由于每一个Selector的处理能力是有限的,因此在大量链接和消息处理过程中,需要考虑如何使用多个Selector.

在非阻塞情况下,read和write都不在是阻塞的,因此需要考虑如何完整的读取到确定的消息;如何在确保在网络环境不是很好的情况下,一定将数据写进IO中。

如何应用ByteBuffer,本身大量创建ByteBuffer就是很耗资源的;如何有效的使用ByteBuffer?同时ByteBuffer的操作需要仔细考虑,因为有position()、mark()、limit()、capacity等方法。

由于每一个线程在处理网络连接的时候,面对的都是一系列的网络连接,需要考虑如何更好的使用、调度多线程。在对消息的处理上,也需要保证一定的顺序,比方说,登录消息***到达,只有登录消息处理之后,才有可能去处理同一个链路上的其他类型的消息。

在网络编程中可能出现的内存泄漏问题。

在NIO的接入处理框架上,大约有两种并发线程:

Selector线程,每一个Selector单独占用一个线程,由于每一个Selector的处理能力是有限的,因此需要多个Selector并行工作。

对于每一条处于Ready状态的链路,需要线程对于相应的消息进行处理;对于这一类型的消息,需要并发线程共同工作进行处理。在这个过程中,不断可能需要消息的完整性;还要涉及到,每个链路上的消息可能有时序,因此在处理上,也可能要求相应的时序性。

当前社区的开源NIO框架实现有MINA、Grizzly、NIO framework、QuickServer、xSocket等,其中MINA和Grizzly最为活跃,而且代码的质量也很高。他们俩在实现的方法上也完全大不一样。(大部分Java的开源服务器都已经用NIO重写了网络部分。 )

关于“Java阻塞的处理方式是怎样的”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Java阻塞的处理方式是怎样的”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网精选频道。

--结束END--

本文标题: Java阻塞的处理方式是怎样的

本文链接: https://lsjlt.com/news/288794.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java阻塞的处理方式是怎样的
    这篇文章主要介绍了Java阻塞的处理方式是怎样的的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java阻塞的处理方式是怎样的文章都会有所收获,下面我们一起来看看吧。在Java1.4以前,Java的网络编程是只有...
    99+
    2023-06-17
  • Java redisTemplate阻塞式处理消息队列的示例分析
    这篇文章主要介绍Java redisTemplate阻塞式处理消息队列的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Redis 消息队列redis五种数据结构队列生产者package c...
    99+
    2023-06-21
  • Java阻塞队列的实现原理是什么
    本篇文章给大家分享的是有关Java阻塞队列的实现原理是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。BlockingQueue接口提供了3个添加元素方法:add:添加元素到...
    99+
    2023-06-17
  • Java异步非阻塞编程的方式有哪些
    这篇文章主要讲解了“Java异步非阻塞编程的方式有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java异步非阻塞编程的方式有哪些”吧!1 服务端执行,最简单的同步调用方式:缺陷:服务端...
    99+
    2023-06-20
  • 执行HttpResponse的请求阻塞太久的处理方法
    执行HttpResponse的请求阻塞太久: 设置请求连接超时时间:在HttpRequest.post()方法后,使用connectTimeout()方法设置连接超时时间。例如:.connectTimeout(3000)表示设置连接超时时...
    99+
    2023-09-03
    服务器 网络 java spring boot spring
  • Java异步非阻塞编程的几种方式总结
    1 服务端执行,最简单的同步调用方式: 缺陷: 服务端响应之前,IO会阻塞在: java.net.SocketInputStream#socketRead0...
    99+
    2024-04-02
  • 基于Redis实现阻塞队列的方式
    日常需求开发过程中,不免会遇到需要通过代码进行异步处理的情况,比如批量发送邮件,批量发送短信,数据导入,为了减少用户的等待,不希望一直菊花转啊转,因此需要进行异步处理,做法就是讲要处...
    99+
    2024-04-02
  • java中interrupt()打断阻塞的操作方法
    这篇文章主要介绍java中interrupt()打断阻塞的操作方法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!常用的java框架有哪些1.SpringMVC,Spring Web MVC是一种基于Java的实现了W...
    99+
    2023-06-15
  • java 打造阻塞式线程池的实例详解
    java 打造阻塞式线程池的实例详解原来以为tiger已经自带了这种线程池,就是在任务数量超出时能够阻塞住投放任务的线程,主要想用在JMS消息监听。开始做法:在ThreadPoolExcecutor中代入new ArrayBlockingQ...
    99+
    2023-05-31
    java 阻塞 线程池
  • 详解Java阻塞队列(BlockingQueue)的实现原理
    阻塞队列 (BlockingQueue)是Java util.concurrent包下重要的数据结构,BlockingQueue提供了线程安全的队列访问方式:当阻塞队列进行插入数据时,如果队列已满,线程将会阻塞等待直到队列非满;从阻塞队列取...
    99+
    2023-05-31
    java 阻塞队列 ava
  • Java中常用阻塞队列的问题是什么
    本篇内容主要讲解“Java中常用阻塞队列的问题是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java中常用阻塞队列的问题是什么”吧!Java常用阻塞队列ArrayBlockingQueue...
    99+
    2023-06-29
  • LinkedBlockingQueue链式阻塞队列的使用和原理解析
    目录概览使用方法1. add | remove | element2. offer | poll | peek3. put | take4. offer | poll (timeou...
    99+
    2022-11-13
    LinkedBlockingQueue 链式阻塞队列 阻塞队列LinkedBlockingQueue
  • 解密Go语言中阻塞操作的实现方式
    Go语言中的阻塞操作是很常见的,例如goroutine之间的通信、channel的操作等。阻塞操作是指在某些条件未满足的情况下程序会停止执行,直到条件满足才会继续执行。解密Go语言中阻...
    99+
    2024-04-02
  • XXL-JOB的阻塞处理策略-单机串行机制
    XXL-JOB的阻塞处理策略-单机串行机制 问题 默认的单机串行策略,是指的是在xxl-job调度时串行,还是指具体的执行器串行 纠结这个问题的起源是在使用xxl-job的时候,配置了两台执...
    99+
    2023-09-12
    服务器 网络 java
  • Java中Struts2处理流程是怎样的
    本篇内容介绍了“Java中Struts2处理流程是怎样的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!看看Struts-2的处理流程:1) ...
    99+
    2023-06-17
  • CSS清理浮动方式是怎样的
    这篇文章给大家介绍CSS清理浮动方式是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。CSS清理浮动有很多种方式,像使用 br 标签自带的 clear 属,使用元素的 overfl...
    99+
    2024-04-02
  • quartz任务阻塞的原因及解决方法是什么
    在Quartz任务调度中,任务阻塞的原因可能有以下几种:1. 任务执行时间过长:如果一个任务执行时间过长,可能会导致后续任务无法按时...
    99+
    2023-10-20
    quartz
  • 异步的魅力:探索 Node.js 中文件读取的非阻塞方式
    ...
    99+
    2024-04-02
  • Java与C#事件处理的对比是怎样的
    本篇文章给大家分享的是有关Java与C#事件处理的对比是怎样的,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。小编分别介绍Java与C#事件处理,包括介绍在C#中,事件(Even...
    99+
    2023-06-17
  • Java线程池submit阻塞获取结果的实现原理详解
    目录前言案例演示和execute区别原理实现RunnableFuture类介绍任务执行run()原理任务结果获取get()原理任务取消cancel()原理总结前言 Java线程池中提...
    99+
    2022-11-13
    Java线程池submit阻塞获取结果 Java 线程池 阻塞获取结果 Java 线程池 阻塞
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作