关于JAVA多线程的那些事__初心者
前言
其实事情的经过也许会复杂了点,这事还得从两个月前开始说。那天,我果断不干IT支援。那天,我立志要做一个真正的程序猿。那天,我26岁11个月。那天,我开始看Android。那天,我一边叨念着有朋自远方来,一边投身了JAVA的怀抱。那天,一切将会改变。
好吧,反正总的来说就是时隔4年半,我又开始搞JAVA了。Eclipse还是Eclipse;NetBeans还是NetBeans;Java被收之后已经来到了7,现在是8;在入手了几本JAVA的书籍后发现《JAVA编程思想》还是这么伟大;开始了新的路途--Android。
下面可能会涉及到一些跟其他框架或者语言比较的情况,比如当下挺火的HTML5,比如越来越火的U3D,比如之前一直从事的WEB应用。然后是我的老朋友JAVA,还有他介绍给我认识的新朋友Android跟之前我或深或浅涉猎过的这些奇奇怪怪的东西做一些比较。当然,主要论述的都是JAVA关于线程这块的一些或技术或心路的历程吧。
我与多线程的那些事
先不从项目说,先说说我对多线程的恐惧。遥想当年读书的时候,JAVA课程设计,老湿给了一个题目,我觉得没啥难度,然后自己立了一个题目,叫两人对战游戏,就是控制两个人跑来跑去然后有攻击防御和技能三个按键,反正就是很弱智的那种。然后老湿说要求用TXT来编,用cmd来调,给一个还是两个星期还是一个月时间去弄,反正我就在最后一个星期管这事。然后我拿着一本JAVA编程思想,两天就把UI写起来,然后就是地狱般的4天,各种各样稀奇古怪的BUG,debug之后触发了更多的bug,然后到了交任务的时候我已经燃烧殆尽了~ 然后由于当初没选老湿的题目已经让老湿很不爽,现在做的这个东西奇奇怪怪的当然被狠批一顿。给了个60多分了事。事后我自己努力了一把,然后就放弃了,删源码,删程序,各种删~ 然后各种自卑,各种觉得自己就是个哔哔,然后看到多线程就尿了~
然后到了工作写的第一个系统,库存ERP系统(这里很感激公司能给一个实习生这么大的空间去发挥啊~)。忽略掉前面那些技术选型啊,噼里啪啦的东西之后到了数据访问这一环,我半天时间就写完了。用的是ASP.NET。但是这里出问题了,因为我用的是直接提交一条SQL语句去执行操作的,然后根据返回的值来判定后面执行的SQL操作。那时我突然想到一个问题,如果两个用户同时用我的SQL语句去操作,而操作的资源这个时候判定是不对的,但是可能由于另外一个用户的同时操作使得这个判定通过了,这怎么弄?(简单来说就是一个同步的问题,那时候还不知道~)
然后就是.NET实现原子性啊,.NET实现事务啊噼里啪啦的东西。到了最后,我把业务逻辑写在了T-SQL存储过程里面,因此这里面的东西充斥着begin tran a; submit tran a; rollback tran a;然后还特意研究了T-SQL事务处理的递归性(具体可以参阅我之前博客的这篇文章:SQL存储过程递归下的事务处理(本身的缺陷还是蛮大的))。然后各种噼里啪啦之后,写T-SQL各种顺手。然后各种各样的逻辑全部写存储过程,然后练就了一双写T-SQL的好手~~
在往后是随着经验值的上涨,我开始密谋架构ERP内核的时候做的单例模式,用于管理用户登录信息。这个时候出现了一种叫线程安全的单例模式,然后就是lock(object){...},不求甚解,直接就上了。关于“线程安全的单例模式”不懂的可以直接复制去问度娘。那时做出来的时候特嚣张,虽然一知半解,也去忽悠别人了~ 反正是能跑,你管俺是真懂的还是蒙中的~
直到……
初体验
各种蛋疼的人事,各种无聊的纠纷,各种倔强的泪水之后,俺从事Android了,俺搞JAVA了~
说下Android跟U3D UI线程方面的不同吧,纯个人或别人观点,有错的话请温柔地指出。U3D的UI线程我们公司的一位专门从事这个领域的哥们说U3D的线程就是一个大轮询,往里面塞任务。简单来说U3D的UI是跑一条线程的(其实想想也是合理的,因为U3D支持多平台发布,其中就包括了Web平台,而JAVAScript就是单线程的)。而Android的UI线程是多线程的,其他线程想要调用Android的UI线程,那就得用handler了,貌似是个钩子的方式做嵌入(详细情况可以参考这里: Android之Handler用法总结 还有钩子的介绍,设计模式之:模板模式)。那么从上面的信息得知Android的UI极有可能是维护一个线程池的。(纯属个人推断,未经考察证实)而Android除了上面的Handler(在其他线程跑UI)之外貌似还提供了一些不错的在UI内部跑其他线程的支援。
然后虽然了解了上面的这些,但是项目的内核还得用JAVA多线程来做,而且跟UI目测没有半毛钱关系。因此吧,就只能老老实实打基础了。有个同事的QQ签名是:当你的才华不足以支撑你的野心时,那你就得多看点书。我觉得很有道理,因此我看书……
Runnable&Thread
开始好多人都说JAVA多线程就是实现Runnable接口或者写Thread类。但是这种说法有时会混熬我们的思维,反正我那时候就是把这两者当成平衡的来看,但其实从现在的应用来说Runnable更多的应该比喻成一个任务(Task),而Thread是管理这个任务的容器。有兴趣的人可以去搜下Thread.start()和Runnable.run()之间的区别。因此很多写过多线程的程序员都会有这种感觉:Runnable用的比Thread要多。而在《JAVA编程思想》里面更是推荐大家用所谓的线程池来管理自己的线程。这里引出了一个概念:线程池。这里可以得出一个结论:线程的管理和线程本身已经分离了。因此这里叫线程已经显得不合适了,这时候换一个称呼可能更加的有助于我们对这个事情的理解。比如把一个Runnable的实例叫“任务”。
1 private Runnable aNewTask = new Runnable()
2 {
3 @Override
4 public void run()
5 {
6 //跑一些奇怪的东西
7 System.out.println("哈哈");
8 }
9 }
10 ExecutorService exec = Executors.newCachedThreadPool();
11 exec.execute(aNewTask);
12 exec.shutdown();
上述就是把一个任务aNewTask放到exec的一个池里面跑,shutdown是关闭池,当然也可以不关闭啦。池有很多种,具体可以看文档或者JAVA编程思想吧。
生产者-消费者模型
这种模型适合的情景:一个资源,两条线程,一条线程负责读,一条线程负责写。
具体可以参阅下面的文章: java实现生产者消费者问题
文章里面提到几种方法,我用到第三种,因此下面是基于JAVA的堵塞队列LinkedBlockingQueue来讨论的。这里的生产者-消费者模型说的比较少,但是他是我整个模型的核心思想。这里有几点我项目的时候犯过的错这里提出来一下:
1. LinkedBlockingQueue里面我存的是一个数组,就是说这是一个数组的队列。而每当我从另外的地方接受了数据之后就传入这个队列,这时候需要把这个传入的数组clone()一次。因为直接传入的那只是一个引用,而非实体,极有可能这个引用的实体在递交给队列之后就会销毁了。这时就只剩下一个地址了。
2. LinkedBlockingQueue是线程安全的,但是如果想要确保一次任务或者一个循环里面多次调用的时候不受干扰,那么还是得用同步锁synchronized去锁定循环体执行的代码。有个资深程序员,同时也是我同学,说:尽量不要用synchronized去锁定资源。而两一位更加资深的工程师也说锁会产生格外的损耗,能不用就不用。但是显然到了我项目里面还得要读写的时候锁死,否则数据就会刷的不整齐了~ 刷不整齐,小伙伴们又有意见了~ 现在想想,其实也真没有锁定的必要啊~ 至于数据会不会丢帧就要留给测试了~。
经过测试: 是可以不用同步锁的~~ 还是那个更加资深的工程师的一句: 合理的安排流程其实可以不用那么多锁的~
3. 虽然跟这个模型不相干,但是还是记录一下。在实施的过程中,我机(dou)智(bi)地把类似于 exec.execute(aNewTask); 这种语句锁了。然后症状就是必须要等这个任务执行完了,这个锁别人的线程才会得到释放~。。可伶我这个一秒锁人家一下的社会青年啊~ 锁出翔了~
项目
先上一张最终的收发设计图吧~
中间那条竖线的意思是接受一个响应的时候才发送下一条数据,夜已深~ 不多介绍项目的细节了。因为整个项目的实施过程基本可以另外再起一篇长文了。比如最开始思考的无堵塞模型(这个非常好玩~~),然后后来编码第一版的基于Channel的发送堵塞模型,然后发现原来下面的东西没有想象中的强悍(羞~),做成这一版的基于Module的发送堵塞模型。好吧写到这里感觉已经在放嘲讽了~
总结
1. 多线程很好玩,思考程序很开心。
2. 帅气的喊一句,当手抚键盘的时候,吾已为神。
3. 白赖先生听到之后投来一个看手(S)表(B)的眼神~
-- 原创的哟,转载请加出处哟 http://www.cnblogs.com/gssl/p/3854512.html 虽然没什么人转的哟 呵呵--
关于JAVA多线程的那些事__初心者的更多相关文章
- java多线程那点事
屌丝程序员们对自己的技术能力总是毫不掩饰的高调,更有甚者每当完成一个简单的功能或算法实现,恨不得从工位上跳起来,生怕谁不知道一样,心情能理解,但个人完全鄙视这种行为.说到底,大家日常的coding,大 ...
- Java多线程编程那些事:volatile解惑--转
http://www.infoq.com/cn/articles/java-multi-thread-volatile/ 1. 前言 volatile关键字可能是Java开发人员“熟悉而又陌生”的一个 ...
- Java多线程(二)关于多线程的CPU密集型和IO密集型这件事
点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...
- java从基础知识(十)java多线程(下)
首先介绍可见性.原子性.有序性.重排序这几个概念 原子性:即一个操作或多个操作要么全部执行并且执行的过程不会被任何因素打断,要么都不执行. 可见性:一个线程对共享变量值的修改,能够及时地被其它线程看到 ...
- Java多线程系列--“JUC集合”03之 CopyOnWriteArraySet
概要 本章是JUC系列中的CopyOnWriteArraySet篇.接下来,会先对CopyOnWriteArraySet进行基本介绍,然后再说明它的原理,接着通过代码去分析,最后通过示例更进一步的了解 ...
- Java多线程编程详解
转自:http://programming.iteye.com/blog/158568 线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Ja ...
- 【转】 Java 多线程之一
转自 Java 多线程 并发编程 一.多线程 1.操作系统有两个容易混淆的概念,进程和线程. 进程:一个计算机程序的运行实例,包含了需要执行的指令:有自己的独立地址空间,包含程序内容和数据:不同进 ...
- Java多线程编程总结(精华)
Java多线程编程总结 2007-05-17 11:21:59 标签:多线程 java 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http ...
- java多线程并发编程与CPU时钟分配小议
我们先来研究下JAVA的多线程的并发编程和CPU时钟振荡的关系吧 老规矩,先科普 我们的操作系统在DOS以前都是单任务的 什么是单任务呢?就是一次只能做一件事 你复制文件的时候,就不能重命名了 那么现 ...
随机推荐
- 【自动化测试】Selenium 下载文件
用curl确定要下载的文件是什么类型的:另一种方法是使用requests 模块来查找内容类型 文件类型 http://tool.oschina.net/commons 1.先设置下载的目录,下载文件的 ...
- 锋利的jQuery读书笔记---jQuery中Ajax--load方法
第一个Ajax例子 <!DOCTYPE html> <html> <head lang="en"> <meta charset=" ...
- C#实现CAD数据转shape或mdb
jojojojo2002 原文C#实现CAD数据转shape或mdb 本文所指的CAD数据为不带空间参考和扩展数据的数据.如果CAD带了空间参考或是扩展属性数据的话,就要采用图形和属性分离的方法转CA ...
- SVN中检出(check out) 和 导出(export) 的区别
SVN是常用的一种常见的版本控制软件.SVN中检出(check out) 和 导出(export) 的区别主要有如下几条: check out跟check in对应,export跟import对应. ...
- Net判断一个对象是否为数值类型 z
http://www.cnblogs.com/SkyD/p/4053461.html public static bool IsNumeric(this Type dataType) { if (da ...
- delphi7如何实现 科学计数的转换。 比如我输入2,触发之后会转换成2.000000E+00.求赐教
uses SysUtils; function StrToExp(s: string): string;var f: Extended;begin f := StrToFloat(s); Result ...
- OpenERP中的会计凭证
OpenERP在采购和销售过程中会自动生成一些会计凭证,这些会计凭证反映了物流和资金流在财务上的处理方式. 仓库入库时 借:库存商品 贷:在途物资 收到供应商发票时 借:在途物资 借:进项税额 贷:应 ...
- bjfu1277 简单递归
比较简单的递归问题.对于第k时刻的图形,可以平均分成四块,左上,右上,左下这三块的图形是一模一样的,右下的那一块不包含红毛僵尸,所以把那三块里的加起来就是结果了. /* * Author : ben ...
- .NET下用C#实现邮箱激活功能
最近要用到安全邮箱激活的功能,故写篇博客记录下. 思路:在表中增加一个字段State来记录邮箱是否激活(0激活,1未激活.) 1.发送邮件. 1-1,给邮箱发送邮件.内容:激活地址+GUID. ...
- 开发环境配置(netbeans+ant迁移到eclipse+maven)
新公司入职,接手一个离职人员的项目,拿到的源码是以一个压缩包,用netbeans开发,ant管理:前端:jsp+extjs,后端:springmvc+hibernate+activiti+spring ...