程序员的自我修养
Home » 分类目录 » Java语言

Java并发编程学习笔记(5)——Fork/Join框架

0条评论12,110次浏览

Fork/Join简介

Fork/Join的核心思想为分治算法:将一个规模较大的问题划分为同样性质但规模较小的若干子问题来求解,然后将子问题的结果汇总并输出最后的结果。Fork/Join框架执行任务时,检查该任务的规模大小,若大于设定的阀值,则划分为更小的子任务,然后继续用框架来执行。若划分后的子问题小于阀值则直接执行,若大于阀值则继续划分成更小的子问题。下图总结了这个概念:
fork-join

核心操作

  • fork操作:把任务分成更小的任务和使用这个框架执行它们。
  • join操作:一个任务等待它创建的任务的结束。

特性

Work-stealing算法,类似Hadoop中的推测执行:一个先完成所有任务的线程会尝试着窃取其它线程中没有完成的任务来执行(任务队列尾部窃取)。这样做的好处是重用利用了并发多线程的优点,并减少了线程间的竞争。

阅读全文>>

标签:,

Java并发编程学习笔记(4)——线程池

0条评论1,480次浏览

从Java5开始,JDK并发API提供了ThreadPoolExecutor类,用来创建线程池。合理的使用线程池,有以下三个好处:

  • 降低资源消耗
  • 提高响应速度
  • 提高线程的可管理性

ThreadPoolExecutor

构造方法

基本构造方法

创建大小固定的线程池

创建大小为1的线程池

常用方法

  • void executeTask(Runnable command),执行Runnable任务
  • void shutdown(),关闭线程池
  • int getPoolSize(),获取线程池大小
  • int getActiveCount(),获取正在运行的线程数量
  • long getCompletedTaskCount(),获取已完成的任务数量
  • Future<T> submit(Callable<T> task),执行Callable任务
  • T invokeAny(Collection<? extends Callable<T>> tasks),执行一组Callable任务,只获取第一个返回结果
  • List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks),执行一组Callable任务,获取全部返回结果

阅读全文>>

标签:,

Java并发编程学习笔记(3)——线程同步进阶

0条评论1,240次浏览

Semaphore

Semaphore是一个控制访问多个共享资源的计数器。当计数器值大于0,代表还有可用资源,线程可以继续访问和使用资源;当计数器的值等于0,代表暂无可用资源,线程必须等待资源的释放。

一个典型的例子就是,有多台打印机,当新的打印任务来时,将检测是否还有可用的打印机,若有则使用,并将可用打印机数量减1;若无则等待;当使用完毕后,释放打印机,将可用打印机数量加1。

使用示例

  • 同Lock一样,Semaphore也可开启公平机制,Semaphore(int permits, boolean fair)
  • acquireUninterruptibly(),与acquire()的区别是:线程中断不会抛出异常
  • tryAcquire(),尝试获取semaphore。如果成功,返回true。如果不成功,返回false值,并不会被阻塞和等待semaphore的释放。

阅读全文>>

标签:,

Java并发编程学习笔记(2)——线程同步基础

0条评论1,118次浏览

synchronized

synchronized关键字用来控制并发访问。每个方法声明为synchronized关键字是一个临界区,Java只允许一个对象执行其中的一个临界区。当synchronized加在静态方法时,代表只有一个执行线程能访问被synchronized关键字声明的静态方法。

synchronized关键字不利于应用程序的性能,所以必须仅在修改共享数据的并发环境下的方法上使用它。应当尽量使用synchronized来保护访问共享数据的代码块,以使得临界区尽可能短。

  • 对于同步方法,锁是当前实例对象
  • 对于静态同步方法,锁是当前对象的Class对象
  • 对于同步方法块,锁是synchronized括号里配置的对象,通常来说会用this;当使用其它对象引用时,代表可以并行的访问。

wait()、notify()、notifyAll()

wait()必须出现在synchronized内,否则会抛出IllegalMonitorStateException异常。当调用wait()后,该线程会睡眠,直到相同对象保护的synchronized代码块中调用notify()或notifyAll()方法才会醒来。在此期间其它线程可以访问synchronized代码块。通常wait()需要配合while循环检查边界条件,否则,当线程唤醒后就会继续执行,而此时可能并不满足线程执行的条件。

阅读全文>>

标签:,

Java并发编程学习笔记(1)——线程基础

0条评论1,126次浏览

写在前面

发现现在学Java的,要是对IO、多线程、并发不熟悉都不好意思出去找工作。现在的新技术日新月异,一味的追求新技术不但沉淀不下多少东西,还得迟早累死。当然不是说不用学新技术,能快速掌握新技术毫无疑问可以增加自己的竞争力,但我觉得打好基础才能以不变应万变,也能更加快速的掌握新技术。其实很多新技术,如Hadoop、HBase等都是前人结合自己的经验写出的框架,真正底层的还是那些基础的东西。

IO、多线程、并发毫无疑问是Java基础中的基础。回想自己做过的项目和产品,要么用的SSH架构,要么是Hadoop这样产品,做开发也快3年了,却一直对IO、多线程、并发不了解,现在开始学习并发编程,并写下学习笔记。

线程基础

创建线程

继承Thread父类

阅读全文>>

标签:,

Java自动适配读取Hdfs和本地文件

1条评论2,967次浏览

开发MR程序通常是在本地跑local MapReduce进行测试,等测试完毕后则将mapred-site.xml放入src下打包成jar放在集群上进行测试。MR若需要读取文件作为数据源,则FileInputFormat.addInputPath(job, new Path(args[0]) );。但有时会出现需要读取Hdfs文件内容但又不能作为数据源输入的场景,比如写HBase MapReduce的时候,输入数据源为HBase的表,但是需要读取Hdfs上某文件的数据来进行操作。

单纯的读取本地文件内容实现起来十分简单,但读取本地文件内容的代码放在集群上是无法使用的。是否有方法能自动适配本地和集群两种模式下的文件读取?通过查找Hadoop API发现可通过FileSystem来实现。具体实现代码如下:

如是本地测试,项目中不包含mapred-site.xml文件(或将其中集群的配置信息注掉),则根据传入的conf则读取本地的文件;反之,添加mapred-site.xml文件,则读取Hdfs上的文件。本地测试时,getResult(conf, "/home/yurnom/data")将读取本地文件or文件夹/home/yurnom/data下面的内容;集群测试时,getResult(conf, "/home/yurnom/data")将读取hdfs://master:9000/home/yurnom/data文件or文件夹下面的内容。

标签:,

Lombok

0条评论4,171次浏览

简介

通过注解形式帮助生成常用的getter、setter等方法,在消除冗长的Java代码上有不错的效果。而且,看起来比较炫酷。

lombok官方网址

原理

没有看过源码,不过想必是通过asm来操控字节码实现的。

对字节码感兴趣的同学可以看看

安装

  • 为何要安装

为了IDE的支持,不然IDE可不知道相应的显示setter、getter方法,编译的时候也不会调用lombok。

  • 安装方式

不同的IDE安装方式不同,详见官网。

此外,我在IntelliJ Idea上安装使用lombok时遇到了一个比较头疼的问题:安装成功了但编译出来的.class文件中却没有相应的方法。若你也遇到了这样的问题,详见

阅读全文>>

分类:Java语言
标签:,

关于String split(String)

1条评论1,363次浏览

"13309970XXX,4,,,1,0,,,,24,0,0,19,0,,,,,,,,0,0,,0,,,,"

今天写MapReduce进行split的时候发现一个问题:

原始数据皆为29个字段,以“,”分隔,结果以上这个字符串经过split后的长度居然是25。

经过打印出分隔后的数组,发现:

length=25
0 : 13309970XXX
1 : 4
2 :
3 :
4 : 1
5 : 0
6 :
7 :
8 :
9 : 24
10 : 0
11 : 0
12 : 19
13 : 0
14 :
15 :
16 :
17 :
18 :
19 :
20 :
21 : 0
22 : 0
23 :
24 : 0

也就是说字符串中最后一个0后面的",,,,"没有成为数组的一部分。

后尝试StringUtils.split(s,","),结果:

length=12
0 : 13309970XXX
1 : 4
2 : 1
3 : 0
4 : 24
5 : 0
6 : 0
7 : 19
8 : 0
9 : 0
10 : 0
11 : 0

更加不是我想要的结果。

最后看了看split的源码,发现split方法调用了split(String, int)方法,尝试s.split(",",29)成功输出想要的结果。

查看split(String, int)源码,发现以下语句导致出现以上的问题,当调用split(String)时limit为0,进入while循环,然后从后向前检查list中item的长度是否为0,若为0,则删除。。。

好吧,不知道为何jdk要这么设计,但好歹可以通过split(String, int)来搞定上面的那个场景。但要是遇到预先并不知道数组的长度而又需要获取正确的(或者称之为原始的)split长度时,该如何处理呢。。?

当然可以自己实现一个split,但也可以使用Guava的Spliter。例如以下代码就可以正确的获取到分隔后的数组:

分类:Java语言
标签:
212
profile
  • 文章总数:79篇
  • 评论总数:254条
  • 分类总数:31个
  • 标签总数:44个
  • 运行时间:1192天

大家好,欢迎来到selfup.cn。

这不是一个只谈技术的博客,这里记录我成长的点点滴滴,coding、riding and everthing!

最新评论
  • Anonymous: :arrow: :neutral: :cry:
  • Anonymous: java.io.NotSerializableExcepti on: DStream checkpointing has been enabled but the DStreams with their...
  • wick: HI,请问一下,U,S,V得到后,怎么得到近似矩阵呢(用sp ark java),谢谢。
  • Michael Whitaker: Thank you for this blog, it was very helpful in troubleshooting my own issues. It seems that no...
  • Anonymous: :mad:
  • Anonymous: :???:
  • Anonymous: :mad: :mad: :mad:
  • 洋流: 哥们,我问个问题,你把testOnborrow去掉了。。如果 得到的jedis资源是个不可用的,服务从来都不出问题么?
  • 洋流: 哥们,我问个问题,你把testOnborrow去掉了。。如果 得到的jedis资源是个不可用的,服务从来都不出问题么?
  • Anonymous: :razz: :evil: :grin:
  • 张瑞昌: 有很多,比较常见的是Jacob迭代法,一次迭代O(n^3), 迭代次数不清楚。 如果是手动算的话按照定义求就可以了
  • Anonymous: :mrgreen:
  • lc277: 你好 我想问下一般删除节点要多久,要删除的datanode大概用了 1t,解除授权已经30多小时还没完成,请问是出现什么问题了吗 麻烦告诉下谢谢 qq1844554123
  • Anonymous: 你好 我想问下一般删除节点要多久,要删除的datanode大概用了 1t,解除授权已经30多小时还没完成,请问是出现什么问题了吗
  • Anonymous: :smile: :grin: :eek:
  • 李雪璇: 想要完整代码,可以帮忙发给我吗
  • Anonymous: 请问一下,那个 user的推荐结果楼主查看了么? 为什么输入数据 最高是五分,输出结果都是7分8分啥的?怎么设置输出的分数的最 大值?
  • Anonymous: 那个 user的推荐结果楼主查看了么? 为什么输入数据 最高是五分,输出结果都是7分8分啥的?
  • Anonymous: stopGracefullyOnShutdown在yarn- client模式下我测试的无效,你的呢
  • Anonymous: 另外,import的lib包能否发个列表.