Java 8 函数式接口 functional interface

Java 8 函数式接口 functional interface http://colobu.com/2014/10/28/secrets-of-java-8-functional-interface/ @FunctionalInterface 函数式接口(Functional Interface)是Java 8对一类特殊类型的接口的称呼。 这类接口只定义了唯一的抽象方法的接口 (除了隐含的Object对象的公共方法) , 因此最开始也就做SAM类型的接口 (Single Abstract Method) 。 为什么会单单从接口中定义出此类接口呢? 原因是在Java Lambda的实现中, 开发组不想再为Lambda表达式单独定义一种特殊的Structural函数类型,称之为箭头类型 (arrow type) , 依然想采用Java既有的类型系统(class, interface, method等), 原因是增加一个结构化的函数类型会增加函数类型的复杂性,破坏既有的Java类型,并对成千上万的Java类库造成严重的影响。 权衡利弊, 因此最终还是利用SAM 接口作为 Lambda表达式的目标类型。 JDK中已有的一些接口本身就是函数式接口,如Runnable。 JDK 8中又增加了java.util.function包, 提供了常用的函数式接口。 函数式接口代表的一种契约, 一种对某个特定函数类型的契约。 在它出现的地方,实际期望一个符合契约要求的函数。 Lambda表达式不能脱离上下文而存在,它必须要有一个明确的目标类型,而这个目标类型就是某个函数式接口。 当然, Java 8发布快一年了, 你对以上的概念也应该有所了解了,这篇文章也不会介绍这些基础的东西, 而是想深入的探讨函数式接口的定义和应用。 JDK 8之前已有的函数式接口 java.lang.Runnable java.util.concurrent.Callable java.security.PrivilegedAction java.util.Comparator java.io.FileFilter java.nio.file.PathMatcher java.lang.reflect.InvocationHandler java.beans.PropertyChangeListener java.awt.event.ActionListener javax.swing.event.ChangeListener 新定义的函数式接口 java.util.function中定义了几组类型的函数式接口以及针对基本数据类型的子接口。 Predicate - 传入一个参数,返回一个bool结果, 方法为boolean test(T t) Consumer - 传入一个参数,无返回值,纯消费。 方法为void accept(T t) ...

2014-12-24 · 4 min · 824 words · -

WinSCP 的四种协议:SFTP(SSH)、FTP、SCP、WebDAV

WinSCP的四种协议:SFTP(SSH)、FTP、SCP、WebDAV 1、FTP FTP(File Transfer Protocol,文件传输协议),通过端口进行文件传输: 端口21,控制链路,用于发送指令给服务器并等待服务器响应; 端口20,数据链路,用来建立数据传输通道。 使用FTP协议可能会存在一些安全隐患,例如FTP服务器软件的漏洞、明文口令、通过FTP服务器进行端口扫描、数据劫持等。 参考:https://baike.baidu.com/item/FTP协议/7651119?fr=aladdin 2.SFTP(SSH) SSH (SSH File Transfer Protocol) 又称 SFTP(Secret File Transfer Protocol),安全文件传送协议,为传输文件提供一种安全的加密方法。 SFTP是SSH内含的协议,只要SSHD服务器启动了就可用,不需要FTP服务器启动才能用。 对网络安全性要求高时,建议使用SFTP。由于SFTP采用加密传输认证信息和数据,所以SFTP十分安全,但是传输效率就比FTP要低的多。 参考:https://baike.baidu.com/item/SSH文件传输协议?fromtitle=sftp&fromid=1184182 3、SCP SCP(secure copy),用来进行远程文件拷贝,使用和SSH相同的认证方式,提供相同的安全保障。 参考:https://www.cnblogs.com/mxh1099/p/5554823.html 4、WebDAV WebDAV一种基于HTTP1.1的扩展协议, 在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法, 使应用程序对Web Server直接读写,并支持写文件锁定及解锁,还可以支持文件的版本控制。 参考:https://baike.baidu.com/item/WebDAV https://www.cnblogs.com/bors/p/WinSCP.html run winscp from cmd winscp.exe /ini="C:\Users\martin\Documents\myconfig.ini"

2014-12-23 · 1 min · 40 words · -

netdata

netdata pacman -S netdata systemctl start netdata systemctl enable netdata vim /etc/netdata/netdata.conf [web] bind to = 0.0.0.0 [::]

2014-12-23 · 1 min · 18 words · -

nginx proxy_pass

nginx proxy_pass 功能 Nginx 的ngx_stream_proxy_module和ngx_http_proxy_module两个模块中,都有 proxy_pass 指令。其主要功能是为后端做代理,协议转发,请求转发等。 二、 用法和区别 官网介绍 ngx_stream_proxy_module 的 proxy_pass 语法:proxy_pass address; 默认值:— 场景:server 段 说明:设置代理服务器的地址。代理地址可以是域名或者IP加端口,也可以是一个UNIX的socket路径 ngx_http_proxy_module 的 proxy_pass 语法:proxy_pass URL; 默认值:— 场景:location 段,location中的if段,limit_except段 说明:设置后端代理服务器的地址和协议,还可以附加可选的URI映射。协议可以是 http 或者 https。地址可以是域名或者IP,可以附加指定端口,也可以是UNIX的socket路径,路径要放在unix: 和 : 之间 区别 从上面的各自说明可以看出两个 proxy_pass 指令都是做后端的代理配置。 除了应用场景的段不同之外,ngx_stream_proxy_module 的 proxy_pass 只能转发域名或IP加端口的请求,即端口转发。 ngx_http_proxy_module 的 proxy_pass 除了包含前者的功能外,还可以实现协议转发,如 http 和 https 与 UNIX socket 三者的相互转发,另外还有很实用的URI转发 用法示例 3.1 ngx_stream_proxy_module 的 proxy_pass server { listen 8000; proxy_pass 127.0.0.1:8080; # IP+端口转发 } server { listen 8000; proxy_pass test.com:8080; # 域名+端口转发 } ...

2014-12-18 · 1 min · 164 words · -

IDEA无法启动,Failed to create JVM,error code -4

IDEA无法启动,Failed to create JVM,error code -4 http://blog.csdn.net/twlkyao/article/details/24534505 发生该错误的原因是因为IDEA需要使用的连续内存空间没有得到满足,解决方案: 1.减小-Xmx和-XX:PermSize的值 切换到IDE_HOME\bin\目录下,找到.exe.vmoptions文件,尝试减少-Xmx和-XX:PermSize的值,建议以100M为单位,直到IDEA可以启动。 2.开启64位模式 IDEA提供idea64.exe的启动器,该启动器使用64位的JDK (需要单独安装) 。 3.使用.bat启动 使用.bat替代.exe启动IDEA。 4.强制使用64位的JDK .bat脚本默认使用32位的JDK (IDEA安装文件的jre 目录下) ,可以通过环境变量强制使用64位的JDK,变量的值取决于你使用的产品,IDEA_JDK for IntelliJ IDEA, WEBIDE_JDK for PhpStorm and WebStorm, PYCHARM_JDK for PyCharm, RUBYMINE_SDK for RubyMine. 参考选择合适的JDK。 5.卸载不常用的应用程序 通过卸载不常用的应用程序来减少应用分割程地址空间。 参考资料: 点击打开链接

2014-12-10 · 1 min · 40 words · -

线程 工作内存

线程 工作内存 计算机的工作方式是基于冯诺依曼结构的,从磁盘读取数据到内存,再从内存读取数据到cpu内部的三级,二级,一级最后到达寄存器。java中的多线程的主内存就是内存上面的 jvm 堆,程序在运行时的线程所要的数据都是来自内存,读取并最终传入cpu内部寄存器,每个cpu内部都有各自的一套完整寄存器,cpu只能直接操作这些寄存器,比如cpu的加法指令吧两个寄存器里面的数据加起来放入其中一个或者地三个寄存器,计算的结果如需要保存,cpu需要另一个指令吧数据传输到数据总线并保存到内存,最终写回磁盘。在这个过程中,内存数据可能被多个线程同时读取,并在cpu内部形成私有的拷贝,就是本地内存 (内存的cpu内部本地副本) 在线程中体现在 线程栈 区,正是这种分步多指令实现一个操作,在多线程被调度置换过程中数据被多个线程操作,造成数据竞争,所以数据经常用到锁等手段实现同步。 上面从硬件的实现角度看,从软件的角度看,线程可访问的数据就分共享数据,和私有数据,这个在不同的计算机编程语言中体现都不一样,比如java中的类属性就可以是共享的也可以是私有的,当这个类的实例是在方法内部创建的,那属性就是线程私有的,因为整个对象都是线程私有的,如果该对象被传到线程中的方法,该对象就是共享的。这个界限就看数据是在哪里产生和多线程可访问性;线程防范内部产生并不被方法外部可访问的数据都是私有数据,多线程编程称为线程安全。相反线程不安全。 Java 虚拟机规范定义了 Java 内存模型来屏蔽掉各种硬件和操作系统的内存差异,达到跨平台的内存访问效果。 为了获得更好的执行性能,Java 内存模型没有限制执行引擎使用处理器的特定缓存器或缓存来和主内存(可以和 RAM类比,但是是虚拟机内存的一部分)交互,工作内存 (可类比高速缓存,也是虚拟机内存的一部分) 为线程私有。 工作内存和主内存的划分和 Java 堆,栈,方法区的划分不同,两者基本没有关系,如果勉强对应,则主内存可理 解为堆中实例数据部分,工作内存则对应栈中部分区域 –引用 «深入理解 JAVA 虚拟机» 线程栈 Execution stack 每个线程都有一个线程栈,线程的每个方法被执行的时候,都会同时创建一个帧 (Frame) 用于存储 本地变量表、操作栈、动态链接、方法出入口等信息。每一个方法的调用至完成,就意味着一个帧在VM栈中的入栈至出栈的过程。如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果VM栈可以动态扩展 (VM Spec中允许固定长度的VM栈) ,当扩展时无法申请到足够内存则抛出 OutOfMemoryError异常。 一个栈帧又分为: 局部变量区、操作数栈和帧数据区。你可以理解 工作内存为局部变量区中的数据。 https://segmentfault.com/q/1010000004885908 https://www.oschina.net/question/1779843_2163094

2014-12-05 · 1 min · 43 words · -

Linux中的各种锁, 自旋锁/spin lock, 排队自旋锁、MCS锁、CLH锁,

Linux中的各种锁, 自旋锁/spin lock, 排队自旋锁、MCS锁、CLH锁 Linux中的各种锁 互斥锁 文件锁 读写锁 Linux作为典型的多用户、多任务、抢占式内核调度的操作系统,为了提高并行处理能力,无论在内核层面还是在用户层面都需要特殊的机制来确保任务的正确性和系统的稳定运行,就如同一个国家需要各种法律条款来约束每个公民的行为,才能有条不紊地运转。 在内核层面涉及到各种软硬件中断、进线程睡眠、抢占式内核调度、多处理器SMP架构等,因此内核在完成自己工作的时候一直在处理这些资源抢占的冲突问题。 在用户层面的进程,虽然Linux作为虚地址模式操作系统,为每个进程开辟了独立的虚拟地址空间,伪独占式拥有资源,但是仍然存在很多场景不得不产生多个进程共享资源的问题,来完成进程间的通信,但是在Go语言中进程间的通信使用消息来完成,处理地更优雅一些。 在线程层面,线程作为进程的一部分,进程内的多个线程只拥有自己的独立堆栈等少量结构,大部分的资源还是过线程共享,因此多线程的资源占用冲突比进程更加明显,所以多线程编程的线程安全问题是个重难点。综上可知,无论在kernel还是user space都必须有一些机制来确保对于资源共享问题的解决,然后这个机制就是接下来要说的: 同步和互斥。 同步和互斥机制 基本概念 同步和互斥的概念有时候很容易混淆,可以简单地认为同步是更加宏观角度的一种说法,互斥是冲突解决的细节方法。所谓同步就是调度者让任务按照约定的合理的顺序进行,但是当任务之间出现资源竞争,也就是竞态冲突时,使用互斥的规则强制约束允许数量的任务占用资源,从而解决各个竞争状态,实现任务的合理运行。 同步和互斥密不可分,有资料说互斥是一种特殊的同步,对此我不太理解,不过实际中想明白细节就行,文字游戏没有意义。 简单来说: 同步与互斥机制是用于控制多个任务对某些特定资源的访问策略 同步是控制多个任务按照一定的规则或顺序访问某些共享资源 互斥是控制某些共享资源在任意时刻只能允许规定数量的任务访问 角色分类 整个协调流程涉及的角色本质上只有三类: 不可独占的共享资源 多个使用者 调度者 调度者需要为多个运行任务制定访问使用规则来实现稳定运行,这个调度者可以是内核、可以是应用程序,具体场景具体分析。 重要术语 要很好地理解同步和互斥,就必须得搞清楚几个重要术语: 竞争冒险(race hazard)或竞态条件(race condition) 最早听说这个术语是在模电数电的课程上,门电路出现竞态条件造成错误的结果,在计算机里面就是多个使用者同时操作共享的变量造成结果的不确定。 临界区 临界区域critical section是指多使用者可能同时共同操作的那部分代码,比如自加自减操作,多个线程处理时就需要对自加自减进行保护,这段代码就是临界区域。 Linux中常用的锁 在说锁之前还需要知道几个东西:信号量和条件变量。这两个东西和锁有一定的联系和区别,在不同的场合单独使用或者配合实现来说实现安全的并发,至于网上很多说互斥锁是一种信号量的特例,对于这种特例理解不了也罢。信号量和互斥锁的场景不一样,信号量主要是资源数量的管理(池化),实际用的频率远不如互斥锁,文字游戏着实无趣,实用主义至上,掌握高频工具的特点正确使用即可,大可不必过于学术派。在使用锁时需要明确几个问题: 锁的所有权问题 谁加锁 谁解锁 解铃还须系铃人 锁的作用就是对临界区资源的读写操作的安全限制 锁是否可以被多个使用者占用(互不影响的使用者对资源的占用) 占用资源的加锁者的释放问题 (锁持有的超时问题) 等待资源的待加锁者的等待问题(如何通知到其他等着资源的使用者) 多个临界区资源锁的循环问题(死锁场景) 带着问题明确想要达到的目的,我们同样可以根据自己的需求设计锁,Linux现有的锁如果从上面几个问题的角度去理解,就非常容易了。 自旋锁 spinlock 自旋锁的主要特征是使用者在想要获得临界区执行权限时,如果临界区已经被加锁,那么自旋锁并不会阻塞睡眠,等待系统来主动唤醒,而是原地忙轮询资源是否被释放加锁,自旋就是自我旋转,这个名字还是很形象的。自旋锁有它的优点就是避免了系统的唤醒,自己来执行轮询,如果在临界区的资源代码非常短且是原子的,那么使用起来是非常方便的,避免了各种上下文切换,开销非常小,因此在内核的一些数据结构中自旋锁被广泛的使用。 互斥锁 mutex 使用者使用互斥锁时在访问共享资源之前对进行加锁操作,在访问完成之后进行解锁操作,谁加锁谁释放,其他使用者没有释放权限。 加锁后,任何其他试图再次加锁的线程会被阻塞,直到当前进程解锁。 区别于自旋锁,互斥锁无法获取锁时将阻塞睡眠,需要系统来唤醒,可以看出来自旋锁自己原地旋转来确定锁被释放了,互斥锁由系统来唤醒,但是现实并不是那么美好的,因为很多业务逻辑系统是不知道的,仍然需要业务线程执行while来轮询是否可以重新加锁。考虑这种情况: 解锁时有多个线程阻塞,那么所有该锁上的线程都被变成就绪状态, 第一个变为就绪状态的线程又执行加锁操作,那么其他的线程又会进入等待,对其他线程而言就是虚假唤醒。 在这种方式下,只有一个线程能够访问被互斥锁保护的资源。 读写锁, 共享互斥锁, rwlock 读写锁也叫共享互斥锁: 读模式共享和写模式互斥,本质上这种非常合理,因为在数据没有被写的前提下,多个使用者读取时完全不需要加锁的。读写锁有读加锁状态、写加锁状态和不加锁状态三种状态,当读写锁在写加锁模式下,任何试图对这个锁进行加锁的线程都会被阻塞,直到写进程对其解锁。 读优先的读写锁: 读写锁 rwlock 默认的也是读优先,也就是:当读写锁在读加锁模式先,任何线程都可以对其进行读加锁操作,但是所有试图进行写加锁操作的线程都会被阻塞,直到所有的读线程都解锁,因此读写锁很适合读次数远远大于写的情况。这种情况需要考虑写饥饿问题,也就是大量的读一直轮不到写,因此需要设置公平的读写策略。在一次面试中曾经问到实现一个写优先级的读写锁,感兴趣的可以想想如何实现。 ...

2014-12-05 · 2 min · 326 words · -

Genymotion

Genymotion Genymotion是一套完整的工具集,旨在为Android提供虚拟环境。开发人员、测试人员、销售人员甚至是游戏玩家都能从中获得众多实用功 能。 它可用于大多数操作系统: Windows、Linux以及MacOS X。它既易于安装,又具备强大的功能: 遵循简单的安装流程指引、选择一款Android虚拟设备、启动工具,大功告成! http://mobile.51cto.com/android-405002.htm Genymotion Android 模拟器一直以速度奇慢无比著称,基本慢到不可用。本文介绍我一直在用的 Genymotion,速度不亚于真机。而且功能齐全,使用简单。 Genymotion 来自于 AndroVM 这个开源项目,基于 x86 和 VirtualBox,支持 OpenGL 加速,可以用于Mac/Win/Linux。最近发布了新版,支持了 Android2.3/4.3,新增了拖拽安装 apk,移除了 Google 市场 (后面提供解决方案) 。另外增加了功能更丰富的付费版,个人可以继续使用免费版。 https://www.imququ.com/post/genymotion.html http://mobile.51cto.com/android-405002.htm

2014-12-04 · 1 min · 29 words · -

Genymotion

Genymotion Genymotion是一套完整的工具集,旨在为Android提供虚拟环境。开发人员、测试人员、销售人员甚至是游戏玩家都能从中获得众多实用功 能。 它可用于大多数操作系统: Windows、Linux以及MacOS X。它既易于安装,又具备强大的功能: 遵循简单的安装流程指引、选择一款Android虚拟设备、启动工具,大功告成! http://mobile.51cto.com/android-405002.htm Genymotion Android 模拟器一直以速度奇慢无比著称,基本慢到不可用。本文介绍我一直在用的 Genymotion,速度不亚于真机。而且功能齐全,使用简单。 Genymotion 来自于 AndroVM 这个开源项目,基于 x86 和 VirtualBox,支持 OpenGL 加速,可以用于Mac/Win/Linux。最近发布了新版,支持了 Android2.3/4.3,新增了拖拽安装 apk,移除了 Google 市场 (后面提供解决方案) 。另外增加了功能更丰富的付费版,个人可以继续使用免费版。 https://www.imququ.com/post/genymotion.html

2014-12-04 · 1 min · 28 words · -

jvm Warmup

jvm Warmup Warmup Warmup 是指在实际进行 benchmark 前先进行预热的行为。为什么需要预热?因为 JVM 的 JIT 机制的存在,如果某个函数被调用多次之后,JVM 会尝试将其编译成为机器码从而提高执行速度。所以为了让 benchmark 的结果更加接近真实情况就需要进行预热。 http://blog.dyngr.com/blog/2016/10/29/introduction-of-jmh/

2014-12-03 · 1 min · 15 words · -

gradle cmd utf8 error

gradle cmd utf8 error export GRADLE_OPTS="-Dfile.encoding=utf-8" add tasks.withType(JavaCompile) { options.encoding = "UTF-8" } The file.encoding system property needs to be set right when the JVM executing the Gradle build (e.g. the Gradle Daemon) starts up. One way to achieve this is with export GRADLE_OPTS="-Dfile.encoding=utf-8". Another way that might work is to add systemProp.file.encoding=utf-8to gradle.properties. Of course this assumes that the build script files are actually using utf-8 encoding. To see what your platform’s (and therefore Gradle’s) default encoding is, print out the system property’s value in a build script. ...

2014-12-03 · 1 min · 91 words · -

Gradle的Properties

Gradle的Properties http://hugozhu.myalert.info/2014/07/23/47-use-gradle-properties-to-set-alternative-android-build-tools.html 目录: 问题背景 解决方案 修改build.gradle使用变量设置版本号 在setting.gradle中设置缺省的版本 在gradle.properties文件中重载版本号 命令行使用 参考链接 问题背景 团队一起在开发一个Android项目,工程师有的使用Eclipse,有个使用Intellij IDEA,有的使用Android Studio。每个人安装的Android SDK build-tools可能都不一样,有的是19.0.3,有的是19.1.0,不同版本的build-tools对Gradle Plugin也有相应的要求,如19.0.3对应的是com.android.tools.build:gradle:0.10.+,19.1.0对应的是com.android.tools.build:gradle:0.12.+,下面是一个典型的build.gradle配置文件。 buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.10.+' } } apply plugin: 'android-library' android { compileSdkVersion 19 buildToolsVersion 19.0.3 defaultConfig { minSdkVersion 8 targetSdkVersion 19 } } 在合作开发中遇到的一个尴尬的问题是,IDEA最新版还不能很好的支持Gradle Plugin 0.12+,而Android Studio最新版则要求使用0.12+。大家又共用一个Git仓库。可能的解决方案是, 从 Git checkout 出来的项目需要有一个基础的版本号,但是开发者可以在本地通过一处文件 (不check in到git) 来重载版本号。 解决方案 Gradle支持三种Properties, 这三种Properties的作用域和初始化阶段都不一样,下面分别列出了其部分特点。: ...

2014-12-03 · 1 min · 191 words · -

Create spring mvc project

Create spring mvc project gradle plugin: apply plugin: ‘idea’ apply plugin: ’eclipse' apply plugin: ‘war’ gradle dependencies: compile(“org.springframework:spring-core:$versionSpring”, “org.springframework:spring-context:$versionSpring”, “org.springframework:spring-web:$versionSpring”, “org.springframework:spring-webmvc:$versionSpring”, “org.springframework:spring-jdbc:$versionSpring”, “org.springframework:spring-orm:$versionSpring” ) web.xml create web.xml in …/webapp/WEB-INF/ http://www.wiloon.com/?p=3459 add context loader listener org.springframework.web.context.ContextLoaderListener spring schema index http://www.springframework.org/schema/beans/ Create controller /JavaEEX/src/main/java/com/wiloon/javaeex/controller/FooController.java create springMvc.xml for eclipse project convert project to web project

2014-12-03 · 1 min · 52 words · -

POSIX

POSIX Pronunciation: /ˈpɒz.ɪks/, pozz-icks POSIX代表 “可移植操作系统接口” Portable Operation System Interface。 在网上查到对于POSIX的介绍,来自《Linux内核设计与实现 (第2版) 》的第5章,就这部分来看,这本书估计不错。 一般情况下,应用程序通过应用编程接口(API)而不是直接通过 系统调用 来编程。这点很重要,因为应用程序使用的这种编程接口实际上并不需要和内核提供的系统调用对应。 一个API定义了一组应用程序使用的编程接口。它们可以实现成一个系统调用,也可以通过调用多个系统调用来实现, 而完全不使用任何系 统调用也不存在问题。 实际上,API可以在各种不同的操作系统上实现,给应用程序提供完全相同的接口,而它们本身在这些系统上的实现却可能迥异。 在Unix世界中,最流行的应用编程接口是基于POSIX标准的。从纯技术的角度看,POSIX是由IEEE的一组标准组成,其目标是提供一套大体上基于Unix的可移植操作系统标准。Linux是与POSIX兼容的。 POSIX是说明API和系统调用之间关系的一个极好例子。在大多数Unix系统上,根据POSIX而定义的API函数和系统调用之间有着直接关 系。实际上,POSIX标准就是仿照早期Unix系统的界面建立的。另一方面,许多操作系统,像Windows NT,尽管和Unix没有什么关系,也提供了与POSIX兼容的库。 Linux的系统调用像大多数Unix系统一样,作为C库的一部分提供 , C库实现了Unix系统的主要API,包括标准C库函数和系统调用。所有的C程序都可以使用C库,而由于C语言本身的特点,其他语言也可以很方便地把它们封装起来使用。此外,C库提供了POSIX的绝大部分API。 图5-1 调用printf()函数时,应用程序、C库和内核之间的关系 从程序员的角度看,系统调用无关紧要;他们只需要跟API打交道就可以了。相反,内核只跟系统调用打交道;库函数及应用程序是怎么使用系统调用不是内核所关心的。 ———这是分割线———– 简单总结: 完成同一功能,不同内核提供的系统调用 (也就是一个函数) 是不同的,例如创建进程,linux下是fork函数,windows下是creatprocess函数。好,我现在在linux下写一个程序,用到fork函数,那么这个程序该怎么往windows上移植?我需要把源代码里的fork通通改成creatprocess,然后重新编译… posix标准的出现就是为了解决这个问题。linux和windows都要实现基本的posix标准,linux把fork函数封装成posix_fork (随便说的) ,windows把creatprocess函数也封装成posix_fork,都声明在unistd.h里。这样,程序员编写普通应用时候,只用包含unistd.h,调用posix_fork函数,程序就在源代码级别可移植了。 POSIX解决什么问题 POSIX解决什么问题 一般情况下,应用程序通过应用编程接口(API)而不是直接通过系统调用来编程(即并不需要和内核提供的系统调用来编程)。一个API定义了一组应用程序使用的编程接口。它们可以实现成调用一个系统,也可以通过调用多个系统来实现,而完全不使用任何系统调用也不存在问题。实际上,API可以在各种不同的操作系统上实现给应用程序提供完全相同的接口,而它们本身在这些系统上的实现却可能迥异。如下图,当应用程序调用printf()函数时,printf函数会调用C库中的printf,继而调用C库中的write,C库最后调用内核的write()。 应用程序、C库和内核之间的关系 从程序员的角度看,系统调用无关紧要,只需要跟API打交道。相反,内核只跟系统调用打交道,库函数及应用程序是怎么系统调用不是内核所关心的。 完成同一功能,不同内核提供的系统调用 (一个函数) 是不同的,例如创建进程,linux下是fork函数,windows下是creatprocess函数。好,我现在在linux下写一个程序,用到fork函数,那么这个程序该怎么往windows上移植?我需要把源代码里的fork通通改成creatprocess,然后重新编译… 主流的操作系统有两种,一种是Windows系统,另一种是Linux系统。由于操作系统的不同,API又分为Windows API和Linux API。在Windows平台开发出来的软件在Linux上无法运行,在Linux上开发的软件在Windows上又无法运行,这就导致了软件移植困难,POSIX(Protabl Operation System 可移植操作系统规范)应运而生。 posix标准的出现就是为了解决这个问题。linux和windows都要实现基本的posix标准,linux把fork函数封装成posix_fork (随便说的) ,windows把creatprocess函数也封装成posix_fork,都声明在unistd.h里。这样,程序员编写普通应用时候,只用包含unistd.h,调用posix_fork函数,程序就在源代码级别可移植了。 posix 是什么? 可移植操作系统接口Portable Operating System Interface of UNIX,POSIX标准定义了操作系统应该为应用程序提供的接口标准,是IEEE为要在各种UNIX操作系统上运行的软件而定义的一系列API标准的总称。 系统调用 (OS call) 系统调用,我们可以理解是操作系统为用户提供的一系列操作的接口 (API) ,这些接口提供了对系统硬件设备功能的操作。这么说可能会比较抽象,举个例子,我们最熟悉的 hello world 程序会在屏幕上打印出信息。程序中调用了 printf() 函数,而库函数 printf 本质上是调用了系统调用 write() 函数,实现了终端信息的打印功能。 ...

2014-12-01 · 2 min · 225 words · -

websocket

websocket https://docs.oracle.com/javaee/7/tutorial/doc/websocket.htm http://blog.csdn.net/chifengxin/article/details/14521093 https://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/ 如何理解 TCP/IP, SPDY, WebSocket 三者之间的关系? http://www.zhihu.com/question/20097129

2014-11-29 · 1 min · 10 words · -

dotnet

dotnet dotnet-sdk-8.0 (开发工具) ├── dotnet-runtime-8.0 (运行时) ├── dotnet-targeting-pack-8.0 (编译支持) ├── dotnet-templates-8.0 (模板) ├── dotnet-apphost-pack-8.0 (发布支持) └── dotnet-host-8.0 (主机) └── dotnet-hostfxr-8.0 (解析器) # 1. 下载并安装Microsoft GPG密钥和仓库配置 wget https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb # wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb rm packages-microsoft-prod.deb # 2. 更新包列表 sudo apt update # 3. 安装.NET 7.0 SDK sudo apt install dotnet-sdk-7.0 ### ------------------------------- sudo dpkg -i packages-microsoft-prod.deb sudo apt-get install -y dotnet-sdk-7.0 sudo apt-get update && sudo apt-get install -y apt-transport-https dotnet --version dotnet --info apt-cache policy dotnet-sdk-8.0 sudo apt install dotnet-sdk-7.0 -y dotnet --list-runtimes dotnet build --verbosity minimal dotnet run --dry-run

2014-11-29 · 1 min · 96 words · -

canvas

canvas 是html5出现的新标签,像所有的dom对象一样它有自己本身的属性、方法和事件,其中就有绘图的方法,js能够调用它来进行绘图

2014-11-29 · 1 min · 2 words · -

java copy file

java copy file http://www.oschina.net/question/565065_58510 private static void nioTransferCopy(File source, File target) { FileChannel in = null; FileChannel out = null; FileInputStream inStream = null; FileOutputStream outStream = null; try { inStream = new FileInputStream(source); outStream = new FileOutputStream(target); in = inStream.getChannel(); out = outStream.getChannel(); in.transferTo(0, in.size(), out); } catch (IOException e) { e.printStackTrace(); } finally { close(inStream); close(in); close(outStream); close(out); } }

2014-11-27 · 1 min · 62 words · -

Java Callable, Future 和 FutureTask

Java Callable, Future 和 FutureTask 创建线程有两种方式,一种是直接继承 Thread,另外一种就是实现 Runnable 接口。 这两种方式都有一个缺陷就是: 在执行完任务之后无法获取执行结果。 如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。 而自从Java 1.5 开始,JDK 提供了 Callable 和 Future, 通过它们可以在任务执行完毕之后得到任务执行结果。 今天我们就来讨论一下 Callable、Future 和 FutureTask 三个类的使用方法。以下是本文的目录大纲: Callable 与 Runnable Future FutureTask 使用示例 Callable 与 Runnable java.lang.Runnable 是一个接口,里面只声明了一个 run() 方法 public interface Runnable { public abstract void run(); } 由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。 Callable 位于 java.util.concurrent 包下,它也是一个接口,在它里面也只声明了一个方法,只不过这个方法叫做 call(): public interface Callable<V> { V call() throws Exception; } 可以看到,这是一个泛型接口,call()函数返回的类型就是传递进来的V类型。 那么怎么使用 Callable 呢? 一般情况下是配合 ExecutorService 来使用的,在 ExecutorService 接口中声明了若干个 submit 方法的重载版本: ...

2014-11-26 · 2 min · 396 words · -

Java assert

Java assert http://lavasoft.blog.51cto.com/62575/43735 一、概述 在C和C++语言中都有assert关键,表示断言。 在Java中,同样也有assert关键字,表示断言,用法和含义都差不多。 二、语法 在Java中,assert关键字是从JAVA SE 1.4 引入的,为了避免和老版本的Java代码中使用了assert关键字导致错误,Java在执行的时候默认是不启动断言检查的 (这个时候,所有的断言语句都将忽略!) ,如果要开启断言检查,则需要用开关-enableassertions或-ea来开启。 assert关键字语法很简单,有两种用法: assert <boolean表达式> 如果<boolean表达式>为true,则程序继续执行。 如果为false,则程序抛出AssertionError,并终止执行。 assert <boolean表达式> : <错误信息表达式> 如果<boolean表达式>为true,则程序继续执行。 如果为false,则程序抛出java.lang.AssertionError,并输入<错误信息表达式>。 三、应用实例 下面给出一个例子,通过例子说明其用法: public class AssertFoo { public static void main(String args[]) { //断言1结果为true,则继续往下执行 assert true; System.out.println(“断言1没有问题,Go!”); System.out.println("\n-----------------\n"); //断言2结果为false,程序终止 assert false : "断言失败,此表达式的信息将会在抛出异常的时候输出!"; System.out.println("断言2没有问题,Go!"); } } 保存代码到C:\AssertFoo.java,然后按照下面的方式执行,查看控制台输出结果: 编译程序: C:>javac AssertFoo.java 默认执行程序,没有开启-ea开关: C:>java AssertFoo 断言1没有问题,Go! 断言2没有问题,Go! 开启-ea开关,执行程序: C:>java -ea AssertFoo 断言1没有问题,Go! Exception in thread “main” java.lang.AssertionError: 断言失败,此表达式的信息将 会在抛出异常的时候输出! at AssertFoo.main(AssertFoo.java:10) ...

2014-11-26 · 1 min · 85 words · -