什么是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 对象的唯一接口

     package sample;  

     import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; public class CopyFile {
public static void main(String[] args) throws Exception {
String infile = "C:\\copy.sql";
String outfile = "C:\\copy.txt";
// 获取源文件和目标文件的输入输出流
FileInputStream fin = new FileInputStream(infile);
FileOutputStream fout = new FileOutputStream(outfile);
// 获取输入输出通道
FileChannel fcin = fin.getChannel();
FileChannel fcout = fout.getChannel();
// 创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
// clear方法重设缓冲区,使它可以接受读入的数据
buffer.clear();
// 从输入通道中将数据读到缓冲区
int r = fcin.read(buffer);
// read方法返回读取的字节数,可能为零,如果该通道已到达流的末尾,则返回-1
if (r == -1) {
break;
}
// flip方法让缓冲区可以将新读入的数据写入另一个通道
buffer.flip();
// 从输出通道中将数据写入缓冲区
fcout.write(buffer);
}
}
}

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

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

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

capacity Buffer容量

Charset 字符编码

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

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

     package nio.readpage;  

     import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.net.InetSocketAddress;
import java.io.IOException;
public class BaiduReader {
private Charset charset = Charset.forName("GBK");// 创建GBK字符集
private SocketChannel channel;
public void readHTMLContent() {
try {
InetSocketAddress socketAddress = new InetSocketAddress(
"www.baidu.com", 80);
//step1:打开连接
channel = SocketChannel.open(socketAddress);
//step2:发送请求,使用GBK编码
channel.write(charset.encode("GET " + "/ HTTP/1.1" + "\r\n\r\n"));
//step3:读取数据
ByteBuffer buffer = ByteBuffer.allocate(1024);// 创建1024字节的缓冲
while (channel.read(buffer) != -1) {
buffer.flip();// flip方法在读缓冲区字节操作之前调用。
System.out.println(charset.decode(buffer));
// 使用Charset.decode方法将字节转换为字符串
buffer.clear();// 清空缓冲
}
} catch (IOException e) {
System.err.println(e.toString());
} finally {
if (channel != null) {
try {
channel.close();
} catch (IOException e) {
}
}
}
}
public static void main(String[] args) {
new BaiduReader().readHTMLContent();
}
}

一个常见的网络 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类的实例。

  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.

  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.

  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.

  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); 
  } 
}

java中 immutable,future,nio的更多相关文章

  1. JAVA中IO和NIO的详解分析,内容来自网络和自己总结

    用一个例子来阐释: 一辆客车上有10个乘客,他们的目的地各不相同,当没有售票员的时候,司机就需要不断的询问每一站是否有乘客需要下车,需要则停下,不需要则继续开车,这种就是阻塞的方式. 当有售票员的时候 ...

  2. 14.Java中的Future模式

    jdk1.7.0_79  本文实际上是对上文<13.ThreadPoolExecutor线程池之submit方法>的一个延续或者一个补充.在上文中提到的submit方法里出现了Future ...

  3. Java中BIO和NIO

    同步/异步.阻塞/非阻塞概念 同步异步 同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication) 同步:在发出一个 ...

  4. java 中AIO,BIO,NIO的区别(茅塞顿开)

    看到知乎上一篇回答,解决了疑惑:https://www.zhihu.com/question/56673416 第三位作者的回答...原谅我没有登录知乎,不然一定给他留赞. 也可以参考:https:/ ...

  5. Java中的Future相关

    先上一个场景:假如你突然想做饭,但是没有厨具,也没有食材.网上购买厨具比较方便,食材去超市买更放心. 实现分析:在快递员送厨具的期间,我们肯定不会闲着,可以去超市买食材.所以,在主线程里面另起一个子线 ...

  6. Java中的Future模式原理自定义实现

    摘要:Future模式类似于js中的ajax等,是一个异步获取数据的机制,这里我把自己的一些形象理解通过代码实现了一下.该机制可以形象的理解为:调用获取数据的方法,首先获得一个没有装数据的空箱子(这个 ...

  7. JAVA中的BIO,NIO,AIO

    在了解BIO,NIO,AIO之前先了解一下IO的几个概念: 1.同步 用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪, 例如自己亲自出马持银行卡到银行取钱 2.异步 用户触发IO操作以后, ...

  8. Java中BIO,NIO,AIO的理解

    在高性能的I/O体系设计中,有几个概念常常会使我们感到迷惑不解.具体如下: 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步非阻塞? 7  ...

  9. Java中BIO、NIO、AIO的区别和应用场景

    学习IO,首先要明白四个东西. 1.同步            java自己去处理io. 2.异步          java将io交给操作系统去处理,告诉缓存区大小,处理完成回调. 3.阻塞     ...

随机推荐

  1. hdu 4915 括号匹配+巧模拟

    http://acm.hdu.edu.cn/showproblem.php?pid=4915 给定一个序列,由()?组成,其中?可以表示(或者),问说有一种.多种或者不存在匹配. 从左向右,优先填满n ...

  2. bootstrap4.2 导航搜索框

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  3. 笔记1:jmeter性能测试使用示例(原文:http://blog.csdn.net/zhongweijian/article/details/7619319)

    jmeter是一个简单开源的纯java的性能测试工具.今天学习了jmeter使用了下jmeter,使用起来非常简单. 如果我们要对163的首页性能进行简单测试,我们可以按照以下步骤进行. 1.在测试计 ...

  4. [smarty] smarty 模板文件中进行字符串与变量的拼接

    // smarty 模板引擎 $arr_tribeLabelList["`$tribe_id`_"]

  5. sql server 字符串分割函数

    ),)) )) as begin ) set @SourceSql=@SourceSql+@StrSeprate while(@SourceSql<>'') begin )) insert ...

  6. 背水一战 Windows 10 (40) - 控件(导航类): AppBar, CommandBar

    [源码下载] 背水一战 Windows 10 (40) - 控件(导航类): AppBar, CommandBar 作者:webabcd 介绍背水一战 Windows 10 之 控件(导航类) App ...

  7. Python中super()的用法

    参考链接:https://www.cnblogs.com/shengulong/p/7892266.html super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是 ...

  8. Linux Shell脚本编程基础(11)

    实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核,不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序.Shel编程语言具有普通编程 ...

  9. solr 下载 有dist目录的(6需要8)

    http://archive.apache.org/dist/lucene/solr/ solr6 需要java8

  10. cad2019卸载/安装失败/如何彻底卸载清除干净cad2019注册表和文件的方法

    cad2019提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装cad2019失败提示cad2019安装未完成,某些产品无法安装,也有时候想重新安装cad2019 ...