w1100n
This site is best viewed in Google Chrome
3/27/2017 13:34

http://blog.csdn.net/lihao21/article/details/48370687 Redis为我们提供了publish/subscribe(发布/订阅)功能。我们可以对某个channel(频道)进行subscribe(订阅),当有人在这个channel上publish(发布)消息时,redis就会通知我们,这样我们可以收到别人发布的消息。 作为Java的redis客户端,Jedis提供了publish/subscribe的接口。本文讲述如何使用Jedis来实现redis的publish/subscribe。 定义Subscriber类 Jedis定义了抽象类JedisPubSub,在这个类中,定义publish/subsribe的回调方法。通过继承JedisPubSub类并重新实现这些回调方法,当publish/subsribe事件发生时,我们可以定制自己的处理逻辑。 在以下例子中,我们定义了Subscriber类,这个类继承了JedisPubSub类,并重新实现了其中的回调方法。 Subscriber.java import redis.clients.jedis.JedisPubSub; public class Subscriber extends JedisPubSub { public Subscriber() { } public void onMessage(String channel, String message) { System.out.println(String.format(“receive redis published message, channel %s, message %s”, channel, message)); } public void onSubscribe(String … Continue reading

3/26/2017 17:13

http://blog.csdn.net/liangxanhai/article/details/7767430   pthread_create函数的详细讲解(包括向线程函数传递参数详解) 标签: threadinclude编译器nulllinuxgcc 2012-07-20 14:52 56250人阅读 评论(4) 收藏 举报 分类: unix高级编程学习(6) 版权声明:本文为博主原创文章,未经博主允许不得转载。 目录(?)[+] pthread_create是UNIX环境创建线程函数头文件 #include<pthread.h>函数声明 int pthread_create(pthread_t*restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict arg);返回值 若成功则返回0,否则返回出错编号 返回成功时,由tidp指向的内存单元被设置为新创建线程的线程ID。attr参数用于制定各种不同的线程属性。新创建的线程从start_rtn函数的地址开始运行,该函数只有一个万能指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg的参数传入。 linux下用C开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread。 由 restrict 修饰的指针是最初唯一对指针所指向的对象进行存取的方法,仅当第二个指针基于第一个时,才能对对象进行存取。对对象的存取都限定于基于由 restrict 修饰的指针表达式中。 由 restrict 修饰的指针主要用于函数形参,或指向由 malloc() 分配的内存空间。restrict 数据类型不改变程序的语义。 编译器能通过作出 restrict 修饰的指针是存取对象的唯一方法的假设,更好地优化某些类型的例程。参数 … Continue reading

3/26/2017 17:09

http://www.cnblogs.com/shangxiaofei/p/5762895.html —->关于时间,创建线程使用是直接向系统申请资源的,这里调用系统函数进行分配资源的话耗时不好说。 —->关于资源,Java线程的线程栈所占用的内存是在Java堆外的,所以是不受java程序控制的,只受系统资源限制,默认一个线程的线程栈大小是1M(当让这个可以通过设置-Xss属性设置,但是要注意栈溢出问题),但是,如果每个用户请求都新建线程的话,1024个用户光线程就占用了1个G的内存,如果系统比较大的话,一下子系统资源就不够用了,最后程序就崩溃了。 —>对操作系统来说,创建一个线程的代价是十分昂贵的, 需要给它分配内存、列入调度,同时在线程切换的时候还要执行内存换页,CPU 的缓存被 清空,切换回来的时候还要重新从内存中读取信息,破坏了数据的局部性。 http://www.cnblogs.com/ktgu/p/3529144.html 多线程的代价      使用多线程往往可以获得更大的吞吐率和更短的响应时间,但是,使用多线程不一定就比单线程程序跑的快,这取决于我们程序设计者的能力以及应用场景的不同。不要为了多线程而多线程,而应考虑具体的应用场景和开发实力,使用多线程就是希望能够获得更快的处理速度和利用闲置的处理能力,如果没带来任何好处还带来了复杂性和一些定时炸弹,那还傻逼了吗?只有在使用多线程给我们带来的好处远大于我们付出的代价时,才考虑使用多线程,有时候可能引入多线程带来的性能提升抵不过多线程而引入的开销,一个没有经过良好并发设计得程序也可能比使用单线程还更慢。 多线程给我们带来的代价 设计更复杂      多线程程序在访问共享数据的时候往往需要我们很小心的处理,否则就会出现难以发现的BUG,一般地,多线程程序往往比单线程程序设计会更加复杂(尽管有些单线程处理程序可能比多线程程序要复杂),而且错误很难重现(因为线程调度的无序性,某些bug的出现依赖于某种特定的线程执行时序)。 上下文切换的开销      线程是由CPU进行调度的,CPU的一个时间片内只执行一个线程上下文内的线程,当CPU由执行线程A切换到执行线程B的过程中会发生一些列的操作,这些操作主要有”保存线程A的执行现场“然后”载入线程B的执行现场”,这个过程称之为“上下文切换(context switch)”,这个上下文切换过程并不廉价,如果没有必要,应该尽量减少上下文切换的发生。 增加更多的资源消耗      除了CPU执行上下文切换的消耗以外,线程的执行还将有其他一些资源的消耗,比如:内存同步的开销(线程需要一些内存在维持线程本地栈,每个线程都有本地独立的栈用以存储线程专用数据),上下文切换的开销(前面已经讲过),线程创建和消亡的开销,以及调度的开销(占用操作系统的一些资源来管理和协调线程),我们可以创建100个线程让他们什么都不做,看看他们消耗了多少内存。 上下文切换      多数人认为使用多线程一定会比单线程执行速度快,但其实未必,因为多线程应用程序会带来额外的开销和竞争问题,他们都可能会拖慢系统的执行速度。这些因素包括:对IO设备的竞争,对锁的竞争,以及CPU对线程执行上下文的频繁切换等。      目前流行的CPU在同一时间内只能运行一个线程,超线程的处理器(包括多核处理器)可以同一时间运行多个线程,linux将多核处理器当作多个单独CPU来识别的。每个进程都会分到CPU的时间片来运行,当某个进程(线程是轻量级进程,他们是可以并行运行的,并且共享地使用他们所属进程的地址空间资源,比如:内存空间或其他资源)当进程用完时间片或者被另一个优先级更高的进程抢占的时候,CPU会将该进程备份到CPU的运行队列中,其他进程被调度在CPU上运行,这个进程切换的过程被称作“上下文切换”,过多的上下文切换会造成系统很大的开销。      在Linux中可以使用vmstat来观察上下文切换的次数,一般来说,空闲的系统,每秒上下文切换次数大概在1500以下。 引起上下文切换的原因 时间片用完,CPU正常调度下一个任务 被其他优先级更高的任务抢占 执行任务碰到IO阻塞,调度器挂起当前任务,切换执行下一个任务 … Continue reading

3/26/2017 13:28

https://www.zhihu.com/question/36964449 公平锁:每个线程抢占锁的顺序为先后调用lock方法的顺序依次获取锁,类似于排队吃饭。 非公平锁:每个线程抢占锁的顺序不定,谁运气好,谁就获取到锁,和调用lock方法的先后顺序无关,类似于堵车时,加塞的那些XXXX。 http://www.infoq.com/cn/articles/jdk1.8-abstractqueuedsynchronizer http://www.infoq.com/cn/articles/java8-abstractqueuedsynchronizer http://ifeve.com/introduce-abstractqueuedsynchronizer/

3/26/2017 13:25

http://www.infoq.com/cn/articles/java-memory-model-2 http://tech.meituan.com/java-memory-reordering.html

3/26/2017 11:00

原文:http://www.ibm.com/developerworks/cn/java/j-jtp10264/index.html 多线程和并发性并不是什么新内容,但是 Java 语言设计中的创新之一就是,它是第一个直接把跨平台线程模型和正规的内存模型集成到语言中的主流语言。核心类库包含一个 Thread 类,可以用它来构建、启动和操纵线程,Java 语言包括了跨线程传达并发性约束的构造 —— synchronized 和volatile 。在简化与平台无关的并发类的开发的同时,它决没有使并发类的编写工作变得更繁琐,只是使它变得更容易了。 synchronized 快速回顾 把代码块声明为 synchronized,有两个重要后果,通常是指该代码具有 原子性(atomicity)和 可见性(visibility)。原子性意味着一个线程一次只能执行由一个指定监控对象(lock)保护的代码,从而防止多个线程在更新共享状态时相互冲突。可见性则更为微妙;它要对付内存缓存和编译器优化的各种反常行为。一般来说,线程以某种不必让其他线程立即可以看到的方式(不管这些线程在寄存器中、在处理器特定的缓存中,还是通过指令重排或者其他编译器优化),不受缓存变量值的约束,但是如果开发人员使用了同步,如下面的代码所示,那么运行库将确保某一线程对变量所做的更新先于对现有synchronized 块所进行的更新,当进入由同一监控器(lock)保护的另一个 synchronized 块时,将立刻可以看到这些对变量所做的更新。类似的规则也存在于 volatile 变量上。 view plain copy synchronized (lockObject) { // update object state } 所以,实现同步操作需要考虑安全更新多个共享变量所需的一切,不能有争用条件,不能破坏数据(假设同步的边界位置正确),而且要保证正确同步的其他线程可以看到这些变量的最新值。通过定义一个清晰的、跨平台的内存模型(该模型在 JDK 5.0 中做了修改,改正了原来定义中的某些错误),通过遵守下面这个简单规则,构建“一次编写,随处运行”的并发类是有可能的: 不论什么时候,只要您将编写的变量接下来可能被另一个线程读取,或者您将读取的变量最后是被另一个线程写入的,那么您必须进行同步。 不过现在好了一点,在最近的 JVM 中,没有争用的同步(一个线程拥有锁的时候,没有其他线程企图获得锁)的性能成本还是很低的。(也不总是这样;早期 JVM 中的同步还没有优化,所以让很多人都这样认为,但是现在这变成了一种误解,人们认为不管是不是争用,同步都有很高的性能成本。) 对 synchronized … Continue reading

3/25/2017 19:12

http://www.meishij.net/zuofa/ganshaonangua.html   南瓜切块 不粘锅加油烧热,入南瓜丁小火煎至表面微焦 生抽,老抽,糖,醋调成烧汁(醋只要加一点点,只是增香,不能吃出酸味来。建议只加生抽,我加了老抽,颜色深了点) 倒入烧汁,大火收汁,并不停翻炒,使南瓜丁均匀裹上烧汁 出锅时多撒些葱花,香喷喷的干烧南瓜就做好了 这个菜做法很简单,但味道却非常的好,至少是我家人喜欢的!趁热吃,真的是香味扑鼻! 只要注意三个要点,做出的干烧南瓜就一定很好吃。第一就是煎的部分,南瓜丁可以切大一些,也不能太薄,这样煎的时候不容易碎,也可以煎的久一些。要煎到南瓜外面都结一层焦皮,这样最后吃起来就是外焦里酥的口感! 还有就是烧汁的调配和使用,烧汁可以根据口感调,我做的就是偏甜一些的口感,但这里面的醋一定不能省,加了少许醋烧出来的南瓜非常的香。不过醋只是增香,不能加太多,否则就有酸味了。烧汁也一定要收干,使其厚厚的包裹在南瓜上,这样才够味,好吃!也才有干烧的感觉! 最后出锅撒的葱花也是功不可没,一定要多撒些,葱香和酱香混合在一起的味道,真的是美妙极了!

3/25/2017 17:11

  默认枚举实例的创建是线程安全的 通过enum关键字来实现枚举,在枚举中需要注意的有: 1. 枚举中的属性必须放在最前面,一般使用大写字母表示 2. 枚举中可以和java类一样定义方法 3. 枚举中的构造方法必须是私有的 通过一个java类来模拟枚举的功能: package org.lkl.imitate_enum; public abstract class WeekDay { public static final WeekDay SUN = new WeekDay() { @Override public WeekDay nextDay() { return MON; } }; public static final WeekDay MON = … Continue reading

3/25/2017 12:15

http://xstarcd.github.io/wiki/Java/JVM_GC.html   JVM gc参数设置与分析 原文: http://hi.baidu.com/i1see1you/item/295c1dc81f91ab55bdef69e5 gc日志分析工具: http://qa.blog.163.com/blog/static/19014700220128199421589/ Java GC 日志图解: http://www.chinasb.org/archives/2012/09/4921.shtml 概述 java的最大好处是自动垃圾回收,这样就无需我们手动的释放对象空间了,但是也产生了相应的负效果,gc是需要时间和资源的,不好的gc会严重影响系统的系能,因此良好的gc是JVM的高性能的保证。JVM堆分为新生代,旧生代和年老代,新生代可用的gc方式有:串行gc(Serial Copying),并行回收gc(Parellel Scavenge),并行gc(ParNew),旧生代和年老代可用的gc方式有串行gc(Serial MSC),并行gc(Parallel MSC),并发gc(CMS)。 回收方式的选择 jvm有client和server两种模式,这两种模式的gc默认方式是不同的: client模式下,新生代选择的是串行gc,旧生代选择的是串行gc server模式下,新生代选择的是并行回收gc,旧生代选择的是并行gc 一般来说我们系统应用选择有两种方式:吞吐量优先和暂停时间优先,对于吞吐量优先的采用server默认的并行gc方式,对于暂停时间优先的选用并发gc(CMS)方式。 CMS gc CMS,全称Concurrent Low Pause Collector,是jdk1.4后期版本开始引入的新gc算法,在jdk5和jdk6中得到了进一步改进,它的主要适合场景是对响应时间的重要性需求大于对吞吐量的要求,能够承受垃圾回收线程和应用线程共享处理器资源,并且应用中存在比较多的长生命周期的对象的应用。CMS是用于对tenured generation的回收,也就是年老代的回收,目标是尽量减少应用的暂停时间,减少full gc发生的几率,利用和应用程序线程并发的垃圾回收线程来标记清除年老代。在我们的应用中,因为有缓存的存在,并且对于响应时间也有比较高的要求,因此希望能尝试使用CMS来替代默认的server型JVM使用的并行收集器,以便获得更短的垃圾回收的暂停时间,提高程序的响应性。 CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停,它的收集周期是这样: 初始标记(CMS-initial-mark) -> 并发标记(CMS-concurrent-mark) -> 重新标记(CMS-remark) -> 并发清除(CMS-concurrent-sweep) ->并发重设状态等待下次CMS的触发(CMS-concurrent-reset)。 … Continue reading

3/25/2017 10:32

http://blog.sina.com.cn/s/blog_605f5b4f01015k56.html http://man.linuxde.net/stat   在Linux中,没有文件创建时间的概念。只有文件的访问时间、修改时间、状态改变时间。也就是说不能知道文件的创建时间。但如果文件创建后就没有修改过,修改时间=创建时间;如果文件创建后,状态就没有改变过,那么状态改变时间=创建时间;如果文件创建后,没有被读取过,那么访问时间=创建时间,这个基本不太可能。 与文件相关的几个时间: 1、访问时间,读一次这个文件的内容,这个时间就会更新。比如对这个文件使用more命令。ls、stat命令都不会修改文件的访问时间。 2、修改时间,对文件内容修改一次,这个时间就会更新。比如:vi后保存文件。ls -l列出的时间就是这个时间。 3、状态改变时间。通过chmod命令更改一次文件属性,这个时间就会更新。查看文件的详细的状态、准确的修改时间等,可以通过stat命令 文件名。 比如: [jing@zhjh c]$ stat temp.c 引用: File: ‘temp.c’ Size: 66 Blocks: 8 IO Block: 4096 \u4e00\u822c\u6587\u4ef6 Device: 807h/2055d Inode: 1191481 Links: 1 Access: (0664/-rw-rw-r–) Uid: ( 500/ jing) Gid: ( … Continue reading

3/25/2017 10:00

https://www.ibm.com/developerworks/cn/java/j-lo-jdk8newfeature/ http://www.ruanyifeng.com/blog/2012/04/functional_programming.html http://www.jianshu.com/p/5b800057f2d8

3/25/2017 9:59

https://www.ibm.com/developerworks/cn/java/j-lo-jdk7-1/ http://blog.ubone.com/blog/2014/11/18/java-7de-6ge-xin-te-xing/   http://www.infoq.com/cn/articles/jdk7-garbage-first-collector

3/24/2017 23:52

http://www.cnblogs.com/shenguanpu/archive/2013/05/05/3060616.html   进程、线程、轻量级进程、协程和go中的Goroutine 那些事儿 电话面试被问到go的协程,曾经的军伟也问到过我协程。虽然用python时候在Eurasia和eventlet里了解过协程,但自己对协程的概念也就是轻量级线程,还有一个很通俗的红绿灯说法:线程要守规则,协程看到红灯但是没有车仍可以通行。现在总结各个资料,从个人理解上说明下 进程 线程 轻量级进程 协程 go中的goroutine 那些事儿。 一、进程 操作系统中最核心的概念是进程,分布式系统中最重要的问题是进程间通信。 进程是“程序执行的一个实例” ,担当分配系统资源的实体。进程创建必须分配一个完整的独立地址空间。 进程切换只发生在内核态,两步:1 切换页全局目录以安装一个新的地址空间 2 切换内核态堆栈和硬件上下文。  另一种说法类似:1 保存CPU环境(寄存器值、程序计数器、堆栈指针)2修改内存管理单元MMU的寄存器 3 转换后备缓冲器TLB中的地址转换缓存内容标记为无效。 二、线程 书中的定义:线程是进程的一个执行流,独立执行它自己的程序代码。 维基百科:线程(英语:thread)是操作系统能够进行运算调度的最小单位。 线程上下文一般只包含CPU上下文及其他的线程管理信息。线程创建的开销主要取决于为线程堆栈的建立而分配内存的开销,这些开销并不大。线程上下文切换发生在两个线程需要同步的时候,比如进入共享数据段。切换只CPU寄存器值需要存储,并随后用将要切换到的线程的原先存储的值重新加载到CPU寄存器中去。 用户级线程主要缺点在于对引起阻塞的系统调用的调用会立即阻塞该线程所属的整个进程。内核实现线程则会导致线程上下文切换的开销跟进程一样大,所以折衷的方法是轻量级进程(Lightweight)。在linux中,一个线程组基本上就是实现了多线程应用的一组轻量级进程。我理解为 进程中存在用户线程、轻量级进程、内核线程。 语言层面实现轻量级进程的比较少,stackless python,erlang支持,java并不支持。 三、协程 协程的定义?颜开、许式伟均只说协程是轻量级的线程,一个进程可轻松创建数十万计的协程。仔细研究下,个人感觉这些都是忽悠人的说法。从维基百科上看,从Knuth老爷子的基本算法卷上看“子程序其实是协程的特例”。子程序是什么?子程序(英语:Subroutine, procedure, function, routine, method, subprogram),就是函数嘛!所以协程也没什么了不起的,就是种更一般意义的程序组件,那你内存空间够大,创建多少个函数还不是随你么? 协程可以通过yield来调用其它协程。通过yield方式转移执行权的协程之间不是调用者与被调用者的关系,而是彼此对称、平等的。协程的起始处是第一个入口点,在协程里,返回点之后是接下来的入口点。子例程的生命期遵循后进先出(最后一个被调用的子例程最先返回);相反,协程的生命期完全由他们的使用的需要决定。 线程和协程的区别: 一旦创建完线程,你就无法决定他什么时候获得时间片,什么时候让出时间片了,你把它交给了内核。而协程编写者可以有一是可控的切换时机,二是很小的切换代价。从操作系统有没有调度权上看,协程就是因为不需要进行内核态的切换,所以会使用它,会有这么个东西。赖永浩和dccmx 这个定义我觉得相对准确  协程-用户态的轻量级的线程。(http://blog.dccmx.com/2011/04/coroutine-concept/) 为什么要用协程: 协程有助于实现: 状态机:在一个子例程里实现状态机,这里状态由该过程当前的出口/入口点确定;这可以产生可读性更高的代码。 … Continue reading

3/24/2017 23:14

http://guojuanjun.blog.51cto.com/277646/321695   wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能.因为都个对像都有锁,锁是每个对像的基础,当然操作锁的方法也是最基础了。 wait导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或被其他线程中断。wait只能由持有对像锁的线程来调用。 notify唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程(随机)。直到当前的线程放弃此对象上的锁,才能继续执行被唤醒的线程。同Wait方法一样,notify只能由持有对像锁的线程来调用.notifyall也一样,不同的是notifyall会唤配所有在此对象锁上等待的线程。 “只能由持有对像锁的线程来调用”说明wait方法与notify方法必须在同步块内执行,即synchronized(obj)之内.再者synchronized代码块内没有锁是寸步不行的,所以线程要继续执行必须获得锁。相辅相成。 看一个很经典的例子(生产者与消费者): package ProductAndConsume; import java.util.List; public class Consume implements Runnable{ private List container = null; private int count; public Consume(List lst){ this.container = lst; } public void run() { while(true){ … Continue reading

3/24/2017 23:09

http://blog.csdn.net/ghsau/article/details/7461369   Java线程(八):锁对象Lock-同步问题更完美的处理方式 标签: javalock同步多线程锁 2012-04-14 22:29 66842人阅读 评论(20) 收藏 举报 分类: Java 线程(14) Java SE(42) 版权声明:本博客所有的原创文章,作者皆保留版权。 Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题,我们拿Java线程(二)中的一个例子简单的实现一下和sychronized一样的效果,代码如下:   view plain copy print? public class LockTest { public static void main(String[] args) { final Outputter1 output = new Outputter1(); new Thread() { public void run() { output.output(“zhangsan”); }; }.start(); new Thread() { public void run() { output.output(“lisi”); }; }.start(); } } … Continue reading

3/24/2017 17:14

http://droidyue.com/blog/2016/03/13/learning-threadlocal-in-java/index.html 提到ThreadLocal,有些Android或者Java程序员可能有所陌生,可能会提出种种问题,它是做什么的,是不是和线程有关,怎么使用呢?等等问题,本文将总结一下我对ThreadLocal的理解和认识,希望让大家理解ThreadLocal更加透彻一些。 ThreadLocal是什么 ThreadLocal是一个关于创建线程局部变量的类。 通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。而使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。 Global && Local 上面的两个修饰看似矛盾,实则不然。 Global 意思是在当前线程中,任何一个点都可以访问到ThreadLocal的值。 Local 意思是该线程的ThreadLocal只能被该线程访问,一般情况下其他线程访问不到。 用法简介 创建,支持泛型 1 ThreadLocal<String> mStringThreadLocal = new ThreadLocal<>(); set方法 1 mStringThreadLocal.set(“droidyue.com”); get方法 1 mStringThreadLocal.get(); 完整的使用示例 1 2 3 4 5 6 7 8 9 10 11 12 … Continue reading

3/24/2017 9:49

http://www.blogjava.net/shijian/archive/2012/04/06/373463.html 1.句柄就是一个标识符,只要获得对象的句柄,我们就可以对对象进行任意的操作。 2.句柄不是指针,操作系统用句柄可以找到一块内存,这个句柄可能是标识符,map的key,也可能是指针,看操作系统怎么处理的了。 fd算是在某种程度上替代句柄吧; Linux 有相应机制,但没有统一的句柄类型,各种类型的系统资源由各自的类型来标识,由各自的接口操作。 3.http://tech.ddvip.com/2009-06/1244006580122204_11.html 在操作系统层面上,文件操作也有类似于FILE的一个概念,在Linux里,这叫做文件描述符(File Descriptor),而在Windows里,叫做句柄(Handle)(以下在没有歧义的时候统称为句柄)。用户通过某个函数打开文件以获得句柄,此 后用户操纵文件皆通过该句柄进行。   设计这么一个句柄的原因在于句柄可以防止用户随意读写操作系统内核的文件对象。无论是Linux还是Windows,文件句柄总是和内核的文件对象相关联的,但如何关联细节用户并不可见。内核可以通过句柄来计算出内核里文件对象的地址,但此能力并不对用户开放。   下面举一个实际的例子,在Linux中,值为0、1、2的fd分别代表标准输入、标准输出和标准错误输出。在程序中打开文件得到的fd从3开始增长。 fd具体是什么呢?在内核中,每一个进程都有一个私有的“打开文件表”,这个表是一个指针数组,每一个元素都指向一个内核的打开文件对象。而fd,就是这 个表的下标。当用户打开一个文件时,内核会在内部生成一个打开文件对象,并在这个表里找到一个空项,让这一项指向生成的打开文件对象,并返回这一项的下标 作为fd。由于这个表处于内核,并且用户无法访问到,因此用户即使拥有fd,也无法得到打开文件对象的地址,只能够通过系统提供的函数来操作。   在C语言里,操纵文件的渠道则是FILE结构,不难想象,C语言中的FILE结构必定和fd有一对一的关系,每个FILE结构都会记录自己唯一对应的fd。 句柄 http://zh.wikipedia.org/wiki/%E5%8F%A5%E6%9F%84 在程序设计 中,句柄是一种特殊的智能指针 。当一个应用程序 要引用其他系统(如数据库、操作系统 )所管理的内存 块或对象 时,就要使用句柄。 句柄与普通指针 的区别在于,指针包含的是引用对象 的内存地址 ,而句柄则是由系统所管理的引用标识,该标识可以被系统重新定位到一个内存地址 上。这种间接访问对象 的模式增强了系统对引用对象 的控制。(参见封装 )。 在上世纪80年代的操作系统(如Mac OS 和Windows )的内存管理 中,句柄被广泛应用。Unix 系统的文件描述符 基本上也属于句柄。和其它桌面环境 一样,Windows API 大量使用句柄来标识系统中的对象 ,并建立操作系统与用户空间 之间的通信渠道。例如,桌面上的一个窗体由一个HWND 类型的句柄来标识。 如今,内存 容量的增大和虚拟内存 算法使得更简单的指针 愈加受到青睐,而指向另一指针的那类句柄受到冷淡。尽管如此,许多操作系统 仍然把指向私有对象 的指针以及进程传递给客户端 的内部数组 下标称为句柄。

3/9/2017 8:03

http://blog.wuxu92.com/golang-package-usage/ 我们都知道Golang中有package的概念。在go源码文件的第一行就是先声明包名: package main 这里的包名是一个标签,不是使用字符串。对于简答的项目可以直接使用main作为包名。 在go的开发中,我们会把所有的项目放到GOPATH/src目录下;与其他语言的项目不同,go的约定是(当前用户)所有的所有项目都是放到这个目录;所以这里面会有很多的项目。一般约定使用域名作为一级的目录,比如GOPATH/src/github.com这个目录存放所有从github获取的项目。 golang中的包全名是相对于GOPATH/src/的相对路径加源码文件中的package声明。源码的文件夹目录可以随意组织,可以有多层级目录,比如我打一个项目放在 GOPATH/src/wuxu.bit/example/alg/sort目录下。里面的一个源码文件sort.go如下: package sort import “fmt” func Sort(a []int) { // do some sort things // fmt.Println(…) } 现在另外一个项目要使用这个排序方法,假设那个项目目录是GOPATH/src/wuxu/weather/目录下的main.go文件。那么要在main.go中import排序文件的包,这里要用完整的包名 package main import ( sort “wuxu.bit/example/alg/sort” “fmt” ) func main() { // can use sort.Sort … Continue reading

3/8/2017 12:12

http://www.iteye.com/topic/473355 什么是逃逸分析(Escape Analysis)? 在编程语言的编译优化原理中,分析指针动态范围的方法称之为逃逸分析。它跟静态代码分析技术中的指针分析和外形分析类似。 通俗一点讲,当一个对象的指针被多个方法或线程引用时,我们称这个指针发生了逃逸。 而用来分析这种逃逸现象的方法,就称之为逃逸分析。 举个例子:   Java代码 class A { public static B b; public void globalVariablePointerEscape() { // 给全局变量赋值,发生逃逸 b = new B(); } public B methodPointerEscape() { // 方法返回值,发生逃逸 return new B(); } public void instancePassPointerEscape() { methodPointerEscape().printClassName(this); // 实例引用传递,发生逃逸 } } class B { public void printClassName(A a) { System.out.println(a.class.getName()); } }     在这个例子中,一共举了3种常见的指针逃逸场景。分别是 全局变量赋值,方法返回值,实例引用传递。   逃逸分析优化JVM原理   我们知道java对象是在堆里分配的,在调用栈中,只保存了对象的指针。 当对象不再使用后,需要依靠GC来遍历引用树并回收内存,如果对象数量较多,将给GC带来较大压力,也间接影响了应用的性能。减少临时对象在堆内分配的数量,无疑是最有效的优化方法。   怎么减少临时对象在堆内的分配数量呢?不可能不实例化对象吧! 场景介绍 其实,在java应用里普遍存在一种场景。一般是在方法体内,声明了一个局部变量,且该变量在方法执行生命周期内未发生逃逸(在方法体内,未将引用暴露给外面)。 按照JVM内存分配机制,首先会在堆里创建变量类的实例,然后将返回的对象指针压入调用栈,继续执行。 … Continue reading

next page
辽ICP备14012896