什么是Future?

用过Java并发包的朋友或许对Future (interface) 已经比较熟悉了,其实Future 本身是一种被广泛运用的并发设计模式,可在很大程度上简化需要数据流同步的并发应用开发。在一些领域语言(如Alice ML )中甚至直接于语法层面支持Future。

这里就以java.util.concurrent.Future 为例简单说一下Future的具体工作方式。Future对象本身可以看作是一个显式的引用,一个对异步处理结果的引用。由于其异步性质,在创建之初,它所引用的对象可能还并不可用(比如尚在运算中,网络传输中或等待中)。这时,得到Future的程序流程如果并不急于使用Future所引用的对象,那么它可以做其它任何想做的事儿,当流程进行到需要Future背后引用的对象时,可能有两种情况:

  • 希望能看到这个对象可用,并完成一些相关的后续流程。如果实在不可用,也可以进入其它分支流程。
  • “没有你我的人生就会失去意义,所以就算海枯石烂,我也要等到你。”(当然,如果实在没有毅力枯等下去,设一个超时也是可以理解的)

对于前一种情况,可以通过调用Future.isDone()判断引用的对象是否就绪,并采取不同的处理;而后一种情况则只需调用get()或
get(long timeout, TimeUnit unit)通过同步阻塞方式等待对象就绪。实际运行期是阻塞还是立即返回就取决于get()的调用时机和对象就绪的先后了。

简单而言,Future模式可以在连续流程中满足数据驱动的并发需求,既获得了并发执行的性能提升,又不失连续流程的简洁优雅。

在Java中,如果需要设定代码执行的最长时间,即超时,可以用Java线程池ExecutorService类配合Future接口来实现。 Future接口是Java标准API的一部分,在java.util.concurrent包中。Future接口是Java线程Future模式的实现,可以来进行异步计算。

Future模式可以这样来描述:我有一个任务,提交给了Future,Future替我完成这个任务。期间我自己可以去做任何想做的事情。一段时间之后,我就便可以从Future那儿取出结果。就相当于下了一张订货单,一段时间后可以拿着提订单来提货,这期间可以干别的任何事情。其中Future 接口就是订货单,真正处理订单的是Executor类,它根据Future接口的要求来生产产品。

Future接口提供方法来检测任务是否被执行完,等待任务执行完获得结果,也可以设置任务执行的超时时间。这个设置超时的方法就是实现Java程序执行超时的关键。


Java NIO 

IO 是主存和外部设备拷贝数据的过程。IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成。

NIO是java new IO的简称,是JDK 1.4提供的新特性,主要包括以下几个方面:

–     为所有的原始类型提供缓存支持。

–     字符集编码解码解决方案。

–     Channel :一个新的原始 I/O 抽象。

–     支持锁和内存映射文件的文件访问接口。

–     提供多路 (non-bloking) 非阻塞式的高伸缩性网络 I/O 。

Buffer Channel

Buffer  是一块连续的内存块,是NIO读写数据的中转站

Channle 数据的源头或者数据的目的地,用于向 buffer 提供数据或者读取 buffer 数据 ,buffer 对象的唯一接口

 1     package sample;
 2
 3     import java.io.FileInputStream;
 4     import java.io.FileOutputStream;
 5     import java.nio.ByteBuffer;
 6     import java.nio.channels.FileChannel;
 7
 8     public class CopyFile {
 9         public static void main(String[] args) throws Exception {
10             String infile = "C:\\copy.sql";
11             String outfile = "C:\\copy.txt";
12             // 获取源文件和目标文件的输入输出流
13             FileInputStream fin = new FileInputStream(infile);
14             FileOutputStream fout = new FileOutputStream(outfile);
15             // 获取输入输出通道
16             FileChannel fcin = fin.getChannel();
17             FileChannel fcout = fout.getChannel();
18             // 创建缓冲区
19             ByteBuffer buffer = ByteBuffer.allocate(1024);
20             while (true) {
21                 // clear方法重设缓冲区,使它可以接受读入的数据
22                 buffer.clear();
23                 // 从输入通道中将数据读到缓冲区
24                 int r = fcin.read(buffer);
25                 // read方法返回读取的字节数,可能为零,如果该通道已到达流的末尾,则返回-1
26                 if (r == -1) {
27                     break;
28                 }
29                 // flip方法让缓冲区可以将新读入的数据写入另一个通道
30                 buffer.flip();
31                 // 从输出通道中将数据写入缓冲区
32                 fcout.write(buffer);
33             }
34         }
35     }  

在Buffer的实现过程中,主要由 position,limit,capacity 三个变量来控制读写的过程

Position 当前写入或读入单位数据数量

limit      代表可以写入或者读入的最大数据量和Buffer容量大小是相同的

capacity Buffer容量

Charset 字符编码

字符编码解码 : 字节码本身只是一些数字,放到正确的上下文中被正确被解析。向 ByteBuffer 中存放数据时需要考虑字符集的编码方式,读取 ByteBuffer 数据时也涉及对字符集解码

Java.nio.charset 提供了编码解码一套解决方案,以http为例,向百度发送请求,并正常的显示。使用到了Charset编码

 1     package nio.readpage;
 2
 3     import java.nio.ByteBuffer;
 4     import java.nio.channels.SocketChannel;
 5     import java.nio.charset.Charset;
 6     import java.net.InetSocketAddress;
 7     import java.io.IOException;
 8     public class BaiduReader {
 9         private Charset charset = Charset.forName("GBK");// 创建GBK字符集
10         private SocketChannel channel;
11         public void readHTMLContent() {
12             try {
13                 InetSocketAddress socketAddress = new InetSocketAddress(
14     "www.baidu.com", 80);
15     //step1:打开连接
16                 channel = SocketChannel.open(socketAddress);
17             //step2:发送请求,使用GBK编码
18                 channel.write(charset.encode("GET " + "/ HTTP/1.1" + "\r\n\r\n"));
19                 //step3:读取数据
20                 ByteBuffer buffer = ByteBuffer.allocate(1024);// 创建1024字节的缓冲
21                 while (channel.read(buffer) != -1) {
22                     buffer.flip();// flip方法在读缓冲区字节操作之前调用。
23                     System.out.println(charset.decode(buffer));
24                     // 使用Charset.decode方法将字节转换为字符串
25                     buffer.clear();// 清空缓冲
26                 }
27             } catch (IOException e) {
28                 System.err.println(e.toString());
29             } finally {
30                 if (channel != null) {
31                     try {
32                         channel.close();
33                     } catch (IOException e) {
34                     }
35                 }
36             }
37         }
38         public static void main(String[] args) {
39             new BaiduReader().readHTMLContent();
40         }
41     }  

一个常见的网络 IO 通讯流程:

Open(打开Socket连接)->Accept(接受连接)->Read(读取请求)->Send(发送响应)->Close(关闭连接)

在Accpet还没有带来之前,会发生阻塞,程序挂起,放弃CPU资源

若数据还没有准备好,Read也会发生阻塞,程序挂起,放弃CPU资源

阻塞式网络IO的特点:多线程处理多个连接,每个线程都有自己的占空间,并占用一些CPU资源,当程序运行所需要的外部资源还没有准备好的时候,

程序会挂起,放弃CPU资源,转而去执行其他的程序。这样的结果是发生大量的上下文切换。

下面有个隐喻:

一辆从 A 开往 B 的公共汽车上,路上有很多点可能会有人下车。司机不知道哪些点会有哪些人会下车,对于需要下车的人,如何处理更好?

1. 司机过程中定时询问每个乘客是否到达目的地,若有人说到了,那么司机停车,乘客下车。 ( 类似阻塞式 )

2. 每个人告诉售票员自己的目的地,然后睡觉,司机只和售票员交互,到了某个点由售票员通知乘客下车。 ( 类似非阻塞 )

很显然,每个人要到达某个目的地可以认为是一个线程,司机可以认为是 CPU 。在阻塞式里面,每个线程需要不断的轮询,上下文切换,以达到找到目的地的结果。而在非阻塞方式里,每个乘客 ( 线程 ) 都在睡觉 ( 休眠 ) ,只在真正外部环境准备好了才唤醒,这样的唤醒肯定不会阻塞。

非阻塞的原理

1  把整个过程切换成小任务,通过任务间协作完成

2 由一个专门的线程处理所有的IO事件,并负责分发

3 事件驱动机制,事件到来的时候触发,而不是同步的去检测

4 线程通讯 多线程之间通过wait 和notify 进行数据通信,保证每次的上下文切换都是有意义的


Java中很多class都是immutable,像String,Integer等,它们通常用来作为Map的key.

那么在实现自定义的Immutable的Class的时候,应该注意哪些要点呢?

a)Class 应该定义成final,避免被继承。

b)所有的成员变量应该被定义成final。

c)不要提供可以改变类状态(成员变量)的方法。【get 方法不要把类里的成员变量让外部客服端引用,当需要访问成员变量时,返回成员变量的copy】

d)构造函数不要引用外部可变对象。如果需要引用外部可以变量,应该在构造函数里进行defensive copy。

an immutable object is an object whose state cannot be modified after it is created.

不可变对象一旦被创建就它的状态就不能被修改。

A classic example of an immutable object is an instance of the Java String class.

不可变对象的一个经典的例子是String类的实例。

Java代码  
  1. String s = "ABC";
  2. s.toLowerCase();

The method toLowerCase() will not change the data "ABC" that s contains.

Instead, a new String object is instantiated(被实例化 ) and given the data "abc" during its construction.

A reference to this String object is returned by the toLowerCase() method.

To make the String s contain the data "abc", a different approach is needed.

Java代码  
  1. s = s.toLowerCase();

Now the String s references a new String object that contains "abc". The String class's methods never affect the data that a String object contains.

For an object to be immutable, there has to be no way to change fields, mutable or not, and to access fields that are mutable.

Here is an example of a mutable object.

Java代码  
  1. import java.util.ArrayList;
  2. import java.util.LinkedList;
  3. import java.util.List;
  4. class Cart {
  5. private final List items;
  6. public Cart(List items) {
  7. this.items = items;
  8. }
  9. public List getItems() {
  10. return items;
  11. }
  12. public static void main(String[] args) {
  13. List list = new ArrayList();
  14. list.add("element1");
  15. Cart cart = new Cart(list);
  16. cart.getItems().add("element2");
  17. // 下面的代码能运行吗?为什么
  18. // list=new LinkedList();
  19. // cart.items=list;
  20. }
  21. }

An instance of this class is not immutable: one can add or remove items either by obtaining the field items by calling getItems() or by retaining(保留,保持 ) a reference to the List object passed when an object of this class is created.

The following change partially solves this problem. In the ImmutableCart class, the list is immutable: you cannot add or remove items.

However, there is no guarantee that the items are also immutable.

One solution is to use the decorator pattern as a wrapper around each of the list's items to make them also immutable.

Java代码  
  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.List;
  4. class ImmutableCart {
  5. private final List items;
  6. public ImmutableCart(List items) {
  7. this.items = Collections.unmodifiableList(new ArrayList(items));
  8. }
  9. public List getItems() {
  10. return items;
  11. }
  12. public static void main(String[] args) {
  13. List list = new ArrayList();
  14. list.add("element1");
  15. ImmutableCart cart = new ImmutableCart(list);
  16. cart.getItems().add("element2");
  17. }
  18. }

运行抛出异常:

Exception in thread "main" java.lang.UnsupportedOperationException

public class Immutable 

  private int data; 
  public Immutable(int initVal) 
  { 
    data=initVal; 
  } 
  public int read() 
  { 
    return data; 
  } 
  public Immutable quadruple() 
  { 
    return new Immutable(data*4); 
  } 
}

转载于:https://www.cnblogs.com/WayneZeng/p/3358457.html

java中 immutable,future,nio相关推荐

  1. java nio 李林峰_浅谈Java中BIO、NIO和AIO的区别和应用场景

    最近一直在准备面试,为了使自己的Java水平更上一个档次,拜读了李林峰老师的<Netty权威指南>,了解了Java关于IO的发展和最新的技术,真是受益匪浅,现在把我总结的关于BIO.NIO ...

  2. 常见的 IO 模型有哪些?Java 中 BIO、NIO、AIO 的区别?

    IO 模型这块确实挺难理解的,需要太多计算机底层知识.写这篇文章用了挺久,就非常希望能把我所知道的讲出来吧!希望朋友们能有收货!为了写这篇文章,还翻看了一下<UNIX 网络编程>这本书,太 ...

  3. Java中IO和NIO的本质和区别

    文章目录 简介 IO的本质 DMA和虚拟地址空间 IO的分类 IO和NIO的区别 总结 简介 终于要写到java中最最让人激动的部分了IO和NIO.IO的全称是input output,是java程序 ...

  4. java中io与nio复制文件性能对比

    2019独角兽企业重金招聘Python工程师标准>>> 1.  在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read( ...

  5. 你了解Java中的Future吗?

    1.概述 在本文中,我们将了解Future.自Java 1.5以来一直存在的接口,在处理异步调用和并发处理时非常有用. 2.创建Future 简单地说,Future类表示异步计算的未来结果 - 这个结 ...

  6. Akka 系列(五):Java 和 Scala 中的 Future

    随着CPU的核数的增加,异步编程模型在并发领域中的得到了越来越多的应用,由于Scala是一门函数式语言,天然的支持异步编程模型,今天主要来看一下Java和Scala中的Futrue,带你走入异步编程的 ...

  7. java中osend_Java中OIO与NIO的简单区别

    原标题:Java中OIO与NIO的简单区别 1.OIO中,每个线程只能处理一个channel(同步的,该线程和该channel绑定). 线程发起IO请求,不管内核是否准备好IO操作,从发起请求起,线程 ...

  8. IO之 java中BIO NIO AIO原理、区别以及应用

    在本篇文章中,我们主要介绍一下java中的BIO NIO AIO,重点是NIO 先说一下同步.异步.阻塞和非阻塞. 简单来讲,同步和异步是针对内核和应用程序之间的交互而言的:阻塞和非阻塞其实是针对进程 ...

  9. 面试官:你知道Java中的回调机制吗?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:22j.co/cFPf          正文    调用和 ...

最新文章

  1. 一个项目在启动前都应该明确哪些事
  2. 设计模式(三)--观察者模式
  3. nfs mysql_heatbeat-gui实现基于nfs的mysql高可用集群
  4. spring序列化_使用@JsonIdentityInfo的Spring自定义序列化器
  5. java gc时自动收dump_Full GC分析:设置Java VM参数实现在Full GC前后自动生成Dump
  6. “阿里离职女高管”蹭马云热度遭阿里高管打假:重新定义高管
  7. 从零开始学前端:jQuery官网 --- 今天你学习了吗?(CSS:Day26)
  8. 微信小程序“信用卡还款”项目实践
  9. docker 下安装oracle
  10. 安装打印机提示未能添加服务器,打印机未能链接到服务器
  11. Python科学绘图 南丁格尔图/玫瑰图
  12. torch.max(action_value, 1)[1].data.numpy()[0] 是什么意思
  13. 电脑死机什么导致,带你一次性了解所有导致电脑死机蓝屏原因!
  14. mysql统计去重记录数量_MySQL分组后,如何统计记录条数
  15. 【Linux】Nvidia显卡驱动安装教程
  16. 分析了一个小说站,速度挺不错的,顺便学习下js
  17. USB接口鼠标接触不良的简单处理
  18. 3. list 方法
  19. 硬件基础知识---(8)如何选取 电容
  20. BUUCTF__[网鼎杯 2018]Fakebook_题解

热门文章

  1. R软件的下载及安装(截图步骤详细)
  2. 2016校招腾讯研发岗笔试题---递归法求解格雷码
  3. MindSDK+yolov5部署及python版图像视频推理实现
  4. Scrapy定向爬虫教程(二)——提取网页内容
  5. 从FM推演各深度学习CTR预估模型
  6. solaris11 format zpool
  7. 正则表达式的一些探索(偏JavaScript)
  8. python的序列化和反序列化
  9. jquery.validate.js插件的使用方法
  10. 虚拟化模板新建虚拟机后 wsus控制台无法看到所有客户端计算机