openjdk

openjdk https://openjdk.org/projects/jdk/ https://jdk.java.net windows install openjdk https://github.com/ojdkbuild/ojdkbuild winget install Microsoft.OpenJDK.21 linux https://github.com/ojdkbuild/contrib_jdk8u-ci https://github.com/ojdkbuild/ojdkbuild/releases/download/java-1.8.0-openjdk-1.8.0.242-1.b08/java-1.8.0-openjdk-1.8.0.242-1.b08.ojdkbuild.windows.x86_64.msi ## archlinux install openjdk # openjdk sudo pacman -S jdk-openjdk sudo pacman -S openjdk-src # jdk8 sudo pacman -S jdk8-openjdk openjdk8-src sudo pacman -S jdk11-openjdk # 查看已经安装的 jdk archlinux-java status sudo archlinux-java set java-11-openjdk sudo pacman -S jdk17-openjdk openjdk17-src 切换 jdk 版本 archlinux-java help archlinux-java status archlinux-java set java-14-openjdk 查看当前 java 版本 java -version sudo archlinux-java status ubuntu openjdk # 安装默认版本, 最新的 TLS 版本 sudo apt update sudo apt install default-jdk # 验证安装 java -version javac -version sudo apt install openjdk-21-jdk sudo apt install openjdk-8-jdk sudo apt install openjdk-8-source # openjdk 17, depends libc6 (>= 2.33) sudo sudo apt update && sudo apt install openjdk-17-jdk openjdk-17-source # 默认目录 ls -l /usr/lib/jvm/ # 查看 sudo update-java-alternatives -l # 切换 jdk sudo update-alternatives --config java 手动安装 openjdk download jdk JDK ...

2017-04-21 · 2 min · 275 words · -

MySQL 共享锁 排他锁

‘MySQL 共享锁 排他锁’ http://www.hollischuang.com/archives/923 共享锁(Share Lock) 共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改 (获取数据上的排他锁) ,直到已释放所有共享锁。 如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。 用法 SELECT … LOCK IN SHARE MODE; 在查询语句后面增加LOCK IN SHARE MODE,MySQL会对查询结果中的每行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。 排他锁 (eXclusive Lock) 排他锁又称写锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。 用法 SELECT … FOR UPDATE; 在查询语句后面增加FOR UPDATE,MySQL会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。 意向锁 意向锁是表级锁,其设计目的主要是为了在一个事务中揭示下一行将要被请求锁的类型。InnoDB中的两个表锁: 意向共享锁 (IS) : 表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁 意向排他锁 (IX) : 类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。 意向锁是InnoDB自动加的,不需要用户干预。 对于insert、update、delete,InnoDB会自动给涉及的数据加排他锁 (X) ;对于一般的Select语句,InnoDB不会加任何锁,事务可以通过以下语句给显示加共享锁或排他锁。 共享锁: SELECT … LOCK IN SHARE MODE; 排他锁: SELECT … FOR UPDATE;

2017-04-12 · 1 min · 58 words · -

MySQL INNODB

MySQL INNODB InnoDB 由 Innobase Oy 公司所开发, 发音为 “in-no-db” http://wulijun.github.io/2012/09/29/MySQL-innodb-intro.html InnoDB是MySQL下使用最广泛的引擎, 它是基于 MySQL 的高可扩展性和高性能存储引擎, 从5.5版本开始, 它已经成为了默认引擎。 InnODB 引擎支持众多特性: 支持ACID,简单地说就是支持事务完整性、一致性; 支持行锁,以及类似ORACLE的一致性读,多用户并发; 独有的聚集索引主键设计方式,可大幅提升并发读写性能; 支持外键; 支持崩溃数据自修复; InnoDB有这么多特性,比MyISAM来的优秀多了,还犹豫什么,果断的切换到InnoDB引擎吧 🙂 InnoDB 配置 可以选择官方版本, 或者 Percon a的分支, 如果不知道在哪下载, 就google吧。安装完MySQL后,需要适当修改下 my.cnf 配置文件, 针对 InnoDB 相关的选项做 一些调整, 才能较好的运行InnoDB。 相关的选项有: #InnoDB存储数据字典、内部数据结构的缓冲池,16MB 已经足够大了。 innodb_additional_mem_pool_size = 16M #InnoDB用于缓存数据、索引、锁、插入缓冲、数据字典等 #如果是专用的DB服务器,且以InnoDB引擎为主的场景,通常可设置物理内存的50% #如果是非专用DB服务器,可以先尝试设置成内存的1/4,如果有问题再调整 #默认值是8M,非常坑X,这也是导致很多人觉得InnoDB不如MyISAM好用的缘故 innodb_buffer_pool_size = 4G #InnoDB共享表空间初始化大小,默认是 10MB,也非常坑X,改成 1GB,并且自动扩展 innodb_data_file_path = ibdata1:1G:autoextend #如果不了解本选项,建议设置为1,能较好保护数据可靠性,对性能有一定影响,但可控 innodb_flush_log_at_trx_commit = 1 #InnoDB的log buffer,通常设置为 64MB 就足够了 innodb_log_buffer_size = 64M #InnoDB redo log大小,通常设置256MB 就足够了 ...

2017-04-11 · 2 min · 289 words · -

MySQL分区表, partition

MySQL分区表, partition 没有分区的表创建分区 partition management on a not partitioned table is not possible ALTER TABLE table0 PARTITION BY RANGE (to_days(field0)) ( PARTITION p201908 VALUES less THAN (737668), PARTITION p201909 VALUES LESS THAN (737698), PARTITION p201910 VALUES LESS THAN (737729), PARTITION p201911 VALUES LESS THAN (737759), PARTITION p201912 VALUES LESS THAN (737790) ) ALTER TABLE table0 PARTITION BY RANGE (to_days(field0)) ( PARTITION p202007 VALUES less THAN (to_days('2020-08-01')), PARTITION p202008 VALUES less THAN (to_days('2020-09-01')), PARTITION p202009 VALUES less THAN (to_days('2020-10-01')), PARTITION p202010 VALUES less THAN (to_days('2020-11-01')), PARTITION p202011 VALUES less THAN (to_days('2020-12-01')), PARTITION p202012 VALUES less THAN (to_days('2021-01-01')), ) 添加分区 alter TABLE table0 add PARTITION ( PARTITION p201908 VALUES less THAN (737668)); alter table table0 add PARTITION ( PARTITION pmax VALUES less than MAXVALUE); -- check partition size USE information_schema; SELECT PARTITION_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 't0' and PARTITION_NAME='p0'; -- drop partition ALTER TABLE `db0`.t0 DROP PARTITION p0; 查看分区的存储情况 SELECT partition_name, PARTITION_DESCRIPTION, PARTITION_EXPRESSION, table_rows FROM information_schema.partitions WHERE table_name = 'table0' 查询 查询的where条件要写完整的时间范围, 只写> 或者只写<, 会导致查询所有的分区. ...

2017-04-07 · 5 min · 981 words · -

archlinux, tensorFlow, golang

archlinux, tensorFlow, golang build tensorflow git clone https://github.com/tensorflow/tensorflow sudo pacman -S bazel sudo pacman -S python-numpy docker run -it -p 8888:8888 gcr.io/tensorflow/tensorflow docker run -it gcr.io/tensorflow/tensorflow bash https://www.tensorflow.org/install/install_linux#InstallingDocker https://www.tensorflow.org/get_started/get_started

2017-04-04 · 1 min · 29 words · -

iowait

iowait iowait 表示在一个采样周期内有百分之几的时间属于以下情况: CPU空闲、并且有仍未完成的 I/O 请求。 对 %iowait 常见的误解有两个: 一是误以为 %iowait 表示 CPU不能工作的时间, 二是误以为 %iowait 表示 I/O有瓶颈。 首先 %iowait 升高并不能证明等待 I/O的进程数量增多了, 也不能证明等待 I/O的总时间增加了。 例如, 在 CPU繁忙期间发生的 I/O, 无论IO是多还是少, %iowait都不会变;当 CPU繁忙程度下降时, 有一部分 IO落入CPU空闲时间段内, 导致%iowait升高。 再比如, IO的并发度低, %iowait就高;IO的并发度高, %iowait可能就比较低。 可见 %iowait是一个非常模糊的指标, 如果看到 %iowait 升高 ,还需检查I/O量有没有明显增加, avserv/avwait/avque 等指标有没有明显增大, 应用有没有感觉变慢,如果都没有,就没什么好担心的。 iowait 的含义为有进程在等 io操作结束 (备份进程) , 并且在等待 io操作结束的过程中, 无其他进程占用cpu, cpu处于空闲状态, 故根据iowait参数无从判断io负载情况,还需要通过iostat来判断备份期间io负载情况 (如备份期间磁盘写性能是否已达瓶颈等) %iowait = (cpu idle time)/(all cpu time) 说明: 高速cpu会造成很高的 iowait值,但这并不代表磁盘是系统的瓶颈。唯一能说明磁盘是系统瓶颈的方法,就是很高的read/write时间,一般来说超过20ms,就代表了不太正常的磁盘性能。为什么是20ms呢?一般来说,一次读写就是一次寻到+一次旋转延迟+数据传输的时间。由于,现代硬盘数据传输就是几微秒或者几十微秒的事情,远远小于寻道时间 (seek time) 220ms和旋转延迟48ms,所以只计算这两个时间就差不多了,也就是15~20ms。只要大于20ms,就必须考虑是否交给磁盘读写的次数太多,导致磁盘性能降低了。 ...

2017-03-31 · 1 min · 154 words · -

Guava cache

Guava cache http://www.cnblogs.com/peida/p/Guava_Cache.html 缓存,在我们日常开发中是必不可少的一种解决性能问题的方法。简单的说,cache 就是为了提升系统性能而开辟的一块内存空间。 缓存的主要作用是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用。在日常开发的很多场合,由于受限于硬盘IO的性能或者我们自身业务系统的数据处理和获取可能非常费时,当我们发现我们的系统这个数据请求量很大的时候,频繁的IO和频繁的逻辑处理会导致硬盘和CPU资源的瓶颈出现。缓存的作用就是将这些来自不易的数据保存在内存中,当有其他线程或者客户端需要查询相同的数据资源时,直接从缓存的内存块中返回数据,这样不但可以提高系统的响应时间,同时也可以节省对这些数据的处理流程的资源消耗,整体上来说,系统性能会有大大的提升。 缓存在很多系统和架构中都用广泛的应用,例如: 1.CPU缓存 2.操作系统缓存 3.本地缓存 4.分布式缓存 5.HTTP缓存 6.数据库缓存 等等,可以说在计算机和网络领域,缓存无处不在。可以这么说,只要有硬件性能不对等,涉及到网络传输的地方都会有缓存的身影。 Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。整体上来说Guava cache 是本地缓存的不二之选,简单易用,性能好。 Guava Cache有两种创建方式: cacheLoader callable callback 通过这两种方法创建的cache,和通常用map来缓存的做法比,不同在于,这两种方法都实现了一种逻辑——从缓存中取key X的值,如果该值已经缓存过了,则返回缓存中的值,如果没有缓存过,可以通过某个方法来获取这个值。但不同的在于cacheloader的定义比较宽泛,是针对整个cache定义的,可以认为是统一的根据key值load value的方法。而callable的方式较为灵活,允许你在get的时候指定。 cacheLoader方式实现实例: @Test public void TestLoadingCache() throws Exception{ LoadingCache<String,String> cahceBuilder=CacheBuilder .newBuilder() .build(new CacheLoader<String, String>(){ @Override public String load(String key) throws Exception { String strProValue=“hello “+key+”!”; return strProValue; } }); System.out.println(“jerry value:"+cahceBuilder.apply(“jerry”)); System.out.println(“jerry value:"+cahceBuilder.get(“jerry”)); System.out.println(“peida value:"+cahceBuilder.get(“peida”)); System.out.println(“peida value:"+cahceBuilder.apply(“peida”)); System.out.println(“lisa value:"+cahceBuilder.apply(“lisa”)); cahceBuilder.put(“harry”, “ssdded”); System.out.println(“harry value:"+cahceBuilder.get(“harry”)); } 输出: jerry value:hello jerry! ...

2017-03-31 · 3 min · 467 words · -

vmstat

vmstat vmstat -SM 1 vmstat 1 10 # vmstat每2秒采集数据,一直采集,直到结束程序 vmstat 2 # 2表示每两秒采集一次服务器状态,1表示只采集一次。 vmstat 2 1 vmstat命令是最常见的 Linux/Unix 监控工具, 可以展现给定时间间隔的服务器的状态值, 包括服务器的 CPU 使用率, 内存使用, 虚拟内存交换情况, IO读写情况。 相比 top, vmstat 可以看到整个机器的 CPU,内存,IO 的使用情况,而不是单单看到各个进程的 CPU 使用率和内存使用率(使用场景不一样)。 -S: 输出信息的单位, (k: 1000, K:1024 , m: 1000000, M: 1048576) bytes, -S, --unit CHAR -a: 显示活动内页 -f: 显示启动后创建的进程总数; -m: 显示slab信息; -n: 头信息仅显示一次 -s: 以表格方式显示事件计数器和内存状态; -d: 报告磁盘状态; -p: 显示指定的硬盘分区状态; 一般vmstat工具的使用是通过两个数字参数来完成的,第一个参数是采样的时间间隔数,单位是秒,第二个参数是采样的次数,如: 输出的字段 r 表示运行队列(就是说多少个进程真的分配到CPU),我测试的服务器目前CPU比较空闲,没什么程序在跑,当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和top的负载有关系,一般负载超过了3就比较高,超过了5就高,超过了10就不正常了,服务器的状态很危险。top的负载类似每秒的运行队列。如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高。 b 表示阻塞的进程,这个不多说,进程阻塞,大家懂的。 swpd swap 的使用量 虚拟内存已使用的大小, 如果大于0, 表示你的机器物理内存不足了, 如果不是程序内存泄露的原因, 那么你该升级内存了或者把耗内存的任务迁移到其他机器。 ...

2017-03-31 · 2 min · 251 words · -

Runtime freeMemory,totalMemory,maxMemory

Runtime freeMemory,totalMemory,maxMemory http://blog.csdn.net/zy_27_ok/article/details/8462385 最近在网上看到一些人讨论到Java.lang.Runtime类中的freeMemory(),totalMemory(),maxMemory ()这几个方法的一些题目,很多人感到很迷惑,为什么,在java程序刚刚启动起来的时候freeMemory()这个方法返回的只有一两兆字节,而随着 java程序往前运行,创建了不少的对象,freeMemory()这个方法的返回有时候不但没有减少,反而会增加。这些人对freeMemory()这 个方法的意义应该有一些误解,他们以为这个方法返回的是操纵系统的剩余可用内存,实在根本就不是这样的。这三个方法反映的都是java这个进程的内存情 况,跟操纵系统的内存根本没有关系。下面结合totalMemory(),maxMemory()一起来解释。 maxMemory()这个方法返回的是java虚拟机 (这个进程) 能构从操纵系统那里挖到的最大的内存,以字节为单位,假如在运行java程 序的时 候,没有添加-Xmx参数,那么就是64兆,也就是说maxMemory()返回的大约是64*1024*1024字节,这是java虚拟机默认情况下能 从操纵系统那里挖到的最大的内存。假如添加了-Xmx参数,将以这个参数后面的值为准,例如java -cp ClassPath -Xmx512m ClassName,那么最大内存就是512*1024*0124字节。 totalMemory()这个方法返回的是java虚拟机现在已经从操纵系统那里挖过来的内存大小,也就是java虚拟机这个进程当时所占用的 所有 内存。假如在运行java的时候没有添加-Xms参数,那么,在java程序运行的过程的,内存总是慢慢的从操纵系统那里挖的,基本上是用多少挖多少,直 挖到maxMemory()为止,所以totalMemory()是慢慢增大的。假如用了-Xms参数,程序在启动的时候就会无条件的从操纵系统中挖- Xms后面定义的内存数,然后在这些内存用的差未几的时候,再往挖。 freeMemory()是什么呢,刚才讲到假如在运行java的时候没有添加-Xms参数,那么,在java程序运行的过程的,内存总是慢慢的 从操 作系统那里挖的,基本上是用多少挖多少,但是java虚拟机100%的情况下是会稍微多挖一点的,这些挖过来而又没有用上的内存,实际上就是 freeMemory(),所以freeMemory()的值一般情况下都是很小的,但是假如你在运行java程序的时候使用了-Xms,这个时候由于程 序在启动的时候就会无条件的从操纵系统中挖-Xms后面定义的内存数,这个时候,挖过来的内存可能大部分没用上,所以这个时候freeMemory()可 能会有些大。 把下面的源代码编译以后,在class文件所在的目录里面,分别用java -cp . Untitled1 和java -cp . -Xms80m -Xmx80m Untitled1 运行,看看结果如何,有助于理解上面的阐述。 public?class?Untitled1?{?????? ??public?Untitled1()?{}?????? ??public?static?void?main(String[]?args)?{?? ????System.out.println(Runtime.getRuntime().freeMemory());?? ????System.out.println(Runtime.getRuntime().totalMemory());?? ????System.out.println(Runtime.getRuntime().maxMemory());?? ????long?t?=?System.currentTimeMillis();?? ????try?{?? ??????Thread.sleep(30000);?? ????}?catch?(Exception?ee)?{?? ??????ee.printStackTrace();?? ????}?? ????String[]?aaa?=?new?String[2000000];?? ????System.out.println(Runtime.getRuntime().freeMemory());?? ????System.out.println(Runtime.getRuntime().totalMemory());?? ????System.out.println(Runtime.getRuntime().maxMemory());?? ????try?{?? ??????Thread.sleep(30000);?? ????}?catch?(Exception?ee)?{?? ??????ee.printStackTrace();?? ????}?? ????for?(int?i?=?0;?i?<?2000000;?i++)?{?? ??????aaa[i]?=?new?String(“aaa”);?? ????}?? ????System.out.println(Runtime.getRuntime().freeMemory());?? ????System.out.println(Runtime.getRuntime().totalMemory());?? ????System.out.println(Runtime.getRuntime().maxMemory());?? ????try?{?? ??????Thread.sleep(30000);?? ????}?catch?(Exception?ee)?{?? ...

2017-03-31 · 1 min · 74 words · -

jvm thread DestroyJavaVM

jvm thread DestroyJavaVM DestroyJavaVM is a thread that unloads the Java VM on program exit. Most of the time it should be waiting, until apocalypse of your VM. Signal Dispatcher is a thread that handles the native signals sent by the OS to your jvm. Finalizer threads pull objects from the finalization queue and calls it finalize method. Reference Handler is a high-priority thread to enqueue pending References. Its defined in java.lang.ref.References.java This happens because most applications are run in threads. ...

2017-03-30 · 2 min · 272 words · -

Java 获取 进程PID

Java 获取 进程PID String name = ManagementFactory.getRuntimeMXBean().getName(); // get pid String pid = name.split("@")[0]; logger.info("PID:{}", pid); 之前并不知道Java中如何能够获取当前进程 (也就是包含当前Java程序的JVM所在进程) 的进程ID,还以为要通过JNI或者通过Runtime.exec执行shell命令等方式才能获取到当前进程的进程ID,今天在偶然中看到一种在Java程序里,获取当前进程ID的方法,记录下来,以后应该会用到: ) 首先,从JDK1.5之后,Java开始提供包: java.lang.management java.lang.management 提供了一系列的用来在运行时管理和监督JVM和OS的管理接口。 今天我将用到的就是这个包中的一个类: ManagementFactory。 当然,这只是java.lang.management包中的一个小功能,该包还提供了很多其他的管理接口,参照java doc如下: Interface Summary ClassLoadingMXBean The management interface for the class loading system of the Java virtual machine. CompilationMXBean The management interface for the compilation system of the Java virtual machine. GarbageCollectorMXBean The management interface for the garbage collection of the Java virtual machine. ...

2017-03-30 · 1 min · 142 words · -

JVM编译器

JVM编译器 即时编译器 Java虚拟机中内置了两个即时编译器,分别为Client和Server或则叫C1和C2. C1编译器将字节码编译为本地代码,进行简单可靠的优化,C2编译器则会启动一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。C1和C2都是编译一些热点代码 (多次调用的方法或者多次执行的循环体) ,因此在编译前,首先要进行热点探测,HotSpot虚拟机中使用的是基于计数器的热点探测方法。 它为每个方法都准备了两个计数器,方法调用计数器和回边计数器。 方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间内方法被调用的次数。当超过一定的时间限度,如果方法调用次数仍然不足以让它提交给即时编译器,那这个方法的调用计数器就会衰减一般,这个过程称为方法调用计数器热度的衰减。 回边计数器统计的是一个方法中循环体代码执行的次数,它没有热度衰减。建立回边计数器统计的目的是为了处罚OSR编译,OSR即栈上替换,也就是编译发生在方法执行过程之中。 http://blog.csdn.net/tingfeng96/article/details/52261219 http://blog.csdn.net/zhuyijian135757/article/details/38391785 https://cyberdak.github.io/jvm/2017/03/25/jvm-restart-cause-high-load

2017-03-30 · 1 min · 12 words · -

Java Scanner

Java Scanner http://blog.csdn.net/carolzhang8406/article/details/6726589 一、扫描控制台输入 这个例子是常常会用到,但是如果没有Scanner,你写写就知道多难受了。 当通过new Scanner(System.in)创建一个Scanner,控制台会一直等待输入,直到敲回车键结束,把所输入的内容传给Scanner,作为扫描对象。如果要获取输入的内容,则只需要调用Scanner的nextLine()方法即可。 /** 扫描控制台输入 @author leizhimin 2009-7-24 11:24:47 */ public class TestScanner { public static void main(String[] args) { Scanner s = new Scanner(System.in); System.out.println(“请输入字符串: “); while (true) { String line = s.nextLine(); if (line.equals(“exit”)) break; System.out.println("»>” + line); } } } 请输入字符串: 234 wer wer bye bye exit Process finished with exit code 0 先写这里吧,有空再继续完善。 二、如果说Scanner使用简便,不如说Scanner的构造器支持多种方式,构建Scanner的对象很方便。 可以从字符串 (Readable) 、输入流、文件等等来直接构建Scanner对象,有了Scanner了,就可以逐段 (根据正则分隔式) 来扫描整个文本,并对扫描后的结果做想要的处理。 三、Scanner默认使用空格作为分割符来分隔文本,但允许你指定新的分隔符 使用默认的空格分隔符: public static void main(String[] args) throws FileNotFoundException { ...

2017-03-30 · 2 min · 269 words · -

pthread

pthread code #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> void* xc(void* arg){ char* c=(char*)arg; printf("参数%s \n",c); int i=0; for (;i<10;i++){ printf("循环%d\n",i); if(i==5){ pthread_exit(1090000000); } } return 100000222; } void main(){ pthread_t tid; pthread_create(&tid,NULL,xc,"线程!!!!"); void *status; pthread_join(tid,&status); printf("返回%d\n",(int)status); } pthread_create pthread.h是UNIX环境创建线程函数头文件 #include<pthread.h> int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict_attr,void * ( *start_rtn)(void *),void *restrict arg); extern int pthread_create (pthread_t *__restrict __newthread, const pthread_attr_t *__restrict __attr, void *(*__start_routine) (void *), void *__restrict __arg) __THROWNL __nonnull ((1, 3)); 若成功则返回0,否则返回出错编号 返回成功时,由 __newthread 指向的内存单元被设置为新创建线程的线程ID。 __attr 参数用于制定各种不同的线程属性。新创建的线程从start_rtn函数的地址开始运行,该函数只有一个万能指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg的参数传入。 linux下用C开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread。 由 restrict 修饰的指针是最初唯一对指针所指向的对象进行存取的方法,仅当第二个指针基于第一个时,才能对对象进行存取。对对象的存取都限定于基于由 restrict 修饰的指针表达式中。 由 restrict 修饰的指针主要用于函数形参,或指向由 malloc() 分配的内存空间。restrict 数据类型不改变程序的语义。 编译器能通过作出 restrict 修饰的指针是存取对象的唯一方法的假设,更好地优化某些类型的例程。参数 第一个参数为指向线程标识符的指针。 第二个参数用来设置线程属性。 第三个参数是线程运行函数的起始地址。 最后一个参数是运行函数的参数。 另外,在编译时注意加上-lpthread参数,以调用静态链接库。因为pthread并非Linux系统的默认库示例 打印线程 IDs #include <pthread.h> ...

2017-03-26 · 2 min · 315 words · -

多线程的代价及上下文切换

多线程的代价及上下文切换 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执行上下文切换的消耗以外,线程的执行还将有其他一些资源的消耗,比如:内存同步的开销 (线程需要一些内存在维持线程本地栈,每个线程都有本地独立的栈用以存储线程专用数据) ,上下文切换的开销 (前面已经讲过) ,线程创建和消亡的开销,以及调度的开销 (占用操作系统的一些资源来管理和协调线程) , 我们可以创建100个线程让他们什么都不做,看看他们消耗了多少内存。 上下文切换 线程是由 CPU 进行调度的, CPU 的一个时间片内只执行一个线程上下文内的线程, 当CPU由执行线程 A 切换到执行线程 B 的过程中会发生一些列的操作, 这些操作主要有"保存线程A的执行现场“然后”载入线程B的执行现场",这个过程称之为"上下文切换 (context switch)",这个上下文切换过程并不廉价, 如果没有必要, 应该尽量减少上下文切换的发生。 多数人认为使用多线程一定会比单线程执行速度快,但其实未必,因为多线程应用程序会带来额外的开销和竞争问题,他们都可能会拖慢系统的执行速度。这些因素包括: 对IO设备的竞争,对锁的竞争,以及CPU对线程执行上下文的频繁切换等。 目前流行的 CPU 在同一时间内只能运行一个线程, 超线程的处理器 (包括多核处理器) 可以同一时间运行多个线程, linux 是将多核处理器当作多个单独 CPU 来识别的。 每个进程都会分到 CPU 的时间片来运行, 当某个进程 (线程是轻量级进程,他们是可以并行运行的,并且共享地使用他们所属进程的地址空间资源, 比如: 内存空间或其他资源 ) 当进程用完时间片或者被另一个优先级更高的进程抢占的时候, CPU会将该进程备份到 CPU 的运行队列中, 其他进程被调度在 CPU 上运行,这个进程切换的过程被称作"上下文切换", 过多的上下文切换会造成系统很大的开销。 ...

2017-03-26 · 1 min · 109 words · -

公平锁, 非公平锁

公平锁, 非公平锁 公平锁: 每个线程抢占锁的顺序为先后调用lock方法的顺序依次获取锁,类似于排队吃饭。 非公平锁: 每个线程抢占锁的顺序不定,谁运气好,谁就获取到锁,和调用lock方法的先后顺序无关,类似于堵车时,加塞的那些XXXX。 如果在绝对时间上,先对锁进行获取的请求一定被先满足,那么这个锁是公平的,反之,是不公平的,也就是说等待时间最长的线程最有机会获取锁,也可以说锁的获取是有序的。 公平的锁机制往往没有非公平的效率高,因为公平的获取锁没有考虑到操作系统对线程的调度因素,这样造成JVM对于等待中的线程调度次序和操作系统对线程的调度之间的不匹配。对于锁的快速且重复的获取过程中,连续获取的概率是非常高的,而公平锁会压制这种情况,虽然公平性得以保障,但是响应比却下降了,但是并不是任何场景都是以TPS作为唯一指标的,因为公平锁能够减少"饥饿"发生的概率,等待越久的请求越是能够得到优先满足。 http://www.infoq.com/cn/articles/jdk1.8-abstractqueuedsynchronizer http://www.infoq.com/cn/articles/java8-abstractqueuedsynchronizer AbstractQueuedSynchronizer的介绍和原理分析 https://www.zhihu.com/question/36964449 ReentrantLock(重入锁)以及公平性 http://ifeve.com/reentrantlock-and-fairness/embed/#?secret=sEU18txaRD

2017-03-26 · 1 min · 14 words · -

重排序 Reorder

重排序 Reorder 编译器和处理器可能会对操作做重排序。编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。 注意,这里所说的数据依赖性仅针对单个处理器中执行的指令序列和单个线程中执行的操作,不同处理器之间和不同线程之间的数据依赖性不被编译器和处理器考虑。 http://www.infoq.com/cn/articles/java-memory-model-2 http://tech.meituan.com/java-memory-reordering.html

2017-03-26 · 1 min · 6 words · -

Java ReentrantLock, synchronized

Java ReentrantLock, synchronized 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 变量上。 synchronized (lockObject) { // update object state } 所以,实现同步操作需要考虑安全更新多个共享变量所需的一切,不能有争用条件, 不能破坏数据 (假设同步的边界位置正确) ,而且要保证正确同步的其他线程可以看到这些变量的最新值。通过定义一个清晰的、跨平台的内存模型 (该模型在 JDK 5.0 中做了修改,改正了原来定义中的某些错误) ,通过遵守下面这个简单规则,构建"一次编写,随处运行"的并发类是有可能的: 不论什么时候,只要您将编写的变量接下来可能被另一个线程读取,或者您将读取的变量最后是被另一个线程写入的,那么您必须进行同步。 不过现在好了一点,在最近的 JVM 中,没有争用的同步 (一个线程拥有锁的时候,没有其他线程企图获得锁) 的性能成本还是很低的。 (也不总是这样;早期 JVM 中的同步还没有优化,所以让很多人都这样认为,但是现在这变成了一种误解,人们认为不管是不是争用,同步都有很高的性能成本。) 对 synchronized 的改进 如此看来同步相当好了,是么?那么为什么 JSR 166 小组花了这么多时间来开发 java.util.concurrent.lock 框架呢? 答案很简单-同步是不错,但它并不完美。它有一些功能性的限制 —— 它无法中断一个正在等候获得锁的线程,也无法通过投票得到锁,如果不想等下去,也就没法得到锁。同步还要求锁的释放只能在与获得锁所在的堆栈帧相同的堆栈帧中进行,多数情况下,这没问题 (而且与异常处理交互得很好) ,但是,确实存在一些非块结构的锁定更合适的情况。 ...

2017-03-26 · 13 min · 2754 words · -

cp command

cp command # 把 dir0 下面的文件和子目录复制到 dir1 # -R, -r, --recursive copy directories recursively cp -r /path/to/dir0/* /path/to/dir1

2017-03-25 · 1 min · 18 words · -

通过枚举enum实现单例设计

通过枚举enum实现单例设计 默认枚举实例的创建是线程安全的 通过enum关键字来实现枚举,在枚举中需要注意的有: 枚举中的属性必须放在最前面,一般使用大写字母表示 枚举中可以和java类一样定义方法 枚举中的构造方法必须是私有的 通过一个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 = new WeekDay() { @Override public WeekDay nextDay() { return SUN; } }; @Override public String toString() { return this == SUN ?“SUN星期天”:“MON星期一” ; } public abstract WeekDay nextDay(); public static void main(String[] args) { System.out.println(WeekDay.SUN.nextDay()); System.out.println(WeekDay.MON.nextDay()); } } 4.可以在枚举属性后面添加()来调用指定参数的构造方法,添加{}来实现其对应的匿名内部类,例如: package org.lkl.imitate_enum; public enum TrafficLamp { RED(30){ ...

2017-03-25 · 2 min · 413 words · -