考
虑以下场景:浏览网页时,浏览器了5个线程下载网页中的图片文件,由于图片大小、网站访问速度等诸多因素的影响,完成图片下载的时间就会有很大的不同。如果先下载完成的图片就会被先显示到界面上,反之,后下载的图片就后显示。
Java的并发库
的CompletionService
可
以满足这种场景要求。该接口有两个重要方法:submit()和take()。submit用于提交一个runnable或者callable,一般会提
交给一个线程池处理;而take就是取出已经执行完毕runnable或者callable实例的Future对象,如果没有满足要求的,就等待了。
Completi ...
在
实际应用中,有时候需要多个线程同时工作以完成同一件事情,而且在完成过程中,往往会等待其他线程都完成某一阶段后再执行,等所有线程都到达某一个阶段后再统一执行。
比如有几个旅行团需要途经深圳、广州、韶关、长沙最后到达武汉。旅行团中有自驾游的,有徒步的,有乘坐旅游大巴的;这些旅行团同时出发,并且每到一个目的地,都要等待其他旅行团到达此地后再同时出发,直到都到达终点站武汉。
这时候CyclicBarrier
就可以派上用场。CyclicBarrier最重要的属性就是参与者个数,另外最要方法是await()。当所有线程都调用了await()后,就表示这些线程都可以继续执行,否则就会等待。
...
Lock
接口
ReentrantLock
是
Lock
的具体类,
Lock
提供了以下一些方法:
lock():
请求锁定,如果锁已被别的线程锁定,调用此方法的线程被阻断进入等待状态。
tryLock()
:如果锁没被别的线程锁定,进入锁定状态,并返回
true
。若锁已被锁定,返回
false
,不进入等待状态。此方法还可带时间参数,如果锁在方法执行时已被锁定,线程将继续等待规定的时间,若还不行才返回
false
。
unlock()
:取消锁定,需要注意的是
Lock
不会自动取消,编程时必须手 ...
*1:
定义了几个任务
*2:
初始了任务执行工具。任务的执行框架将会在后面解释。
*3:
执行任务,任务启动时返回了一个
Future
对象,如果想得到任务执行的结果或者是异常可对这个
Future
对象进行操作。
Future
所含的值必须跟
Callable
所含的值对映,比如说例子中
Future
对印
Callable
*4:
任务
1
正常执行完毕,
future1.get()
会返回线程的值
*5:
任务
2
在进行一个死循环,调用
future2.cancel(true)
来中止此 ...
Java自
1995
年面世以来得到了广泛得一个运用,但是对多线程编程的支持
Java
很长时间一直停留在初级阶段。在
Java 5.0
之前
Java
里的多线程编程主要是通过
Thread
类,
Runnable
接口,
Object
对象中的
wait()
、
notify()
、
notifyAll()
等方法和
synchronized
关键词来实现的。这些工具虽然能在大多数情况下解决对共享资源的管理和线程间的调度,但存在以下几个问题
1. &nbs ...
本文探讨用信号量Semaphore实现互斥锁Mutex的问题
在Doug lea的那本著名的《Java并发编程—设计原则与模式》,英文名"Concurrent Programming in Java™: Design Principles and Patterns, Second Edition
",书中提到可以用信号量Semaphore实现互斥锁Mutex。虽然java中是通过synchronize关键字提供锁,并用这个基础设施实现信号量的。在有的系统中只有信号量这一原语,锁是通过信号量实现的。代码如下: ...
操作系统的信号量是个很重要的概念,在进程控制方面都有应用。Java
并发库
的Semaphore
可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,acquire()获取一个许可,如果没有就等待,而release()释放一个许可。比如在Windows下可以设置共享文件的最大客户端访问个数。
Semaphore维护了当前访问的个数,提供同步机制,控制同时访问的个数。在数据结构中链表可以保存“无限”的节点,用Semaphore可以实现有限大小的链表。另外重入锁ReentrantLock也可以实现该功能,但实现上要负责些,代码也要复杂 ...
本文是Sun官方以Blog形式发布的Java
核心技术窍门(Java
C
oreTechTip)中的一个。本文主要介绍了C
allable及其相关接口和类的使用,篇幅不长且易于理解,故翻译在了此处,相信对于准备或刚接触java.util.concurrent的朋友会有所帮助。
自从Java平台的最开始,Runnable接口就已存在了。它允许你定义一个可由线程完成的任务。如大多数人所已知的那样,它只提供了一个run方法,
该方法既不接受任何参数,也 ...
run()
和start() 是大家都很熟悉的两个方法。把希望并行处理的代码都放在run() 中;stat()
用于自动调用run(),这是JAVA的内在机制规定的。并且run()
的访问控制符必须是public,返回值必须是void(这种说法不准确,run() 没有返回值),run()不带参数。
闲话少说,我们要讲的是join(),我们首先来看个例子:
代码:
/**
* @author QingHe
* Creation on 2005-12-19
*/
public class ThreadTest impleme ...
最
近JDK6 RC
已经发布了,而对于JDK5
的新特性还来不及使用,虽然在项目中还没有使用,但可以写一些Demo体验一下Tiger的魅力,现在的时代就是体验的时代,事事都要亲历亲为才能有发言权,怎么有点毛主席“实事求是”的感觉。
JDK5中的一个亮点就是将Doug Lea
的并发库
引入到Java标准库中。Doug Lea确实是一个牛人,能教书,能出书,能编码,不过这在国外还是比较普遍的,而国内的教授们就相差太远了。
一般的服务器都需要线程池,比如Web、FTP等服务器,不过它们一般都自己实现了线程池,比如以前介绍过的Tomcat
、Resin和 ...
并
发库中的BlockingQueue
是一个比较好玩的类,顾名思义,就是阻塞队列。该类主要提供了两个方法put()和take(),前者将一个对象放到队列中,如果队列已经满了,就等待直到有空闲节点;后者从head取一个对象,如果没有对象,就等待直到有可取的对象。
下面的例子比较简单,一个读线程,用于将要处理的文件对象添加到阻塞队列中,
另外四个写线程用于取出文件对象,为了模拟写操作耗时长的特点,特让线程睡眠一段随机长度的时间。另外,该Demo也使用到了线程池和原子整型
(AtomicInteger),AtomicInteger可以在并发情况下达到原子化更新,避免使用了synchron ...
从
名字可以看出,CountDownLatch
是一个倒数计数的锁,当倒数到0时触发事件,也就是开锁,其他人就可以进入了。在一些应用场合中,需要等待某个条件达到要求后才能做后面的事情;同时当线程都完成后也会触发事件,以便进行后面的操作。
CountDownLatch最重要的方法是countDown()和await(),前者主要是倒数一次,后者是等待倒数到0,如果没有到达0,就只有阻塞等待了。
一个CountDouwnLatch实例是不能重复使用的,也就是说它是一次性的,锁一经被打开就不能再关闭使用了,如果想重复使用,请考虑使用CyclicBarrier
。
下面的例子简单的说明 ...
在JAVA中,通过其对线程类的内嵌支持,编程人员编写多线程程序是很简易的。然而,在编程人员面前,多线程呈现出一组新的难题,如果没有被恰当的解决,将导致意外的行为以及细微的、难以发现的错误。在本篇文章中,我们针对这些难题之一:如何中断一个正在运行的线程。
背景
中断(Interrupt)一个线程意味着在该线程完成任务之前停止其正在进行的一切,有效地中止其当前的操作。线程是死亡、还是等待新的任务或是继续运行至下一步,就取决于这个程序。
虽然初次看来它可能显得简单,但是,你必须进行一些预警以实现期望的结果。你最好还是牢记以下的几点告诫。
首先,忘掉T ...
Thread.stop
, Thread.suspend
, Thread.resume
和Runtime.runFinalizersOnExit
这些终止线程运行的方法已经被废弃,使用它们是极端不安全的!
现在,如果你要安全有效地终止一个线程,应该采用以下这些方法:
1,线程正常执行完毕,正常结束。
也就是让run方法执行完毕,该线程就会正常结束。
2,监视某些条件,结束线程的不间断运行。
然而,常常有些线程是伺服线程。它们需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。
通常,它们执 ...
3.4 不可变性
为了满足同步的需要,另一种方法是使用不可变对象[EJ
Item13]。到目前为止,几乎所有我们已经描述过的原子性与可见性的危险,比如访问过期数据,未及时更新或者观察一个处于不一致状态的对象,它们都产
生于多线程下各种难以预测的行为协同工作,多个线程总试图同时访问相同的可变状态。如果对象的状态不能被修改,这些风险与复杂度就自然而然地消失了。
创建后状态不能被修改的对象叫做不可变对象。不可变对象天生是线程安全的。它们的常量(域)是在构造函数中创建的。既然它们的状态无法被修改,这些常量永远不会变。
不可变对象永远是线程安全的。
...
使用多个 Java 线程之间共享数据的缺点在于数据访问必须同步,从而避免出现不一致的内容视图,后者可能会导致应用程序失败。例如,Hashtable
类的 put()
和 get()
方法是同步的。因为需要实现同步,所以 put()
和 get()
方法在执行时将同时单独地访问数据;否则,应用程序数据结构可能会被破坏。
当某个应用程序的线程频繁访问这些方法,导致线程出现阻塞时,这些方法的同步点将成为瓶颈。每次只能有一个线程获得内容的访问权。而其他线程必须等
待。如果线程出现排队等候(如果不是这样,线程能够进行其他有用操作),性能和吞吐量将下降。当性能分析显示同步方法实际上 ...
本文探讨了一个常见的线程方面的危险:在构造过程中,允许this引用脱逃
。
这个看上去没什么危害的做法,实际上可能在Java程序中造成无法预料和不期望的结果。
“this引用逃脱”造成问题的本质就是,外部线程获得了一个没有完全构筑的对象!
测试和调试多线程程序是非常困难的,因为并发性方面的危险常常是以不一致的方式显现出来。多数线程问题都是很难预料的,设置在某些平台上(如单处
理器系统),或者低于一定的负载,问题可能根本就不出现。
由于测试多线程程序的正确性是如此困难,以及查找错误如此费时,因此从一开始开发应用程序就要在心中牢记线程的安全性,这 ...
大家都知道java构造 的使用方法吧,
可能大家都用它来进行对象的初始化。
就像下面这样一个例子。
public
class
Test
...
{
public
static
void
main(String [] args)
...
{
& ...
不变对象具备许多能更方便地使用他们的特性,包括不严格的同步需求和不必考虑数据讹误就能自由地共享和高速缓存对象引用。尽管不变性可能未必对于任何类都
有意义,但大多数程式中至少有一些类将受益于不可变。在本月的 Java 理论和实践中,Brian Goetz
说明了不变性的一些长处和构造不变类的一些准则。请在附带的论坛中和作者和其他读者分享您关于本文的心得。(也能够单击文章顶部或底部的“讨论”来访问论
坛。)
不变对象是指在实例化后其外部可见状态无法更改的对象。Java 类库中的 String、Integer 和 BigDecimal 类就是不变对象的示例 &mda ...
同步的基本规则:只要读取可能由其他线程写入的变量,或者写入随后由其他线程读取的变量,就必须进行同步。很容易“忘记”这个规则,特别是在读取时。
多线程
是一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间相互独立。多线程和传统的单线程在程序设计上最大的区别在于,由于各个线程的控制流彼此独立,使得各个线程之间的代码
是乱序执行的。任何线程都有四种状态:产生(New),可执行(Runnable),阻塞(Blocked),死亡(Dead)。
1.Java
的多线程
在 Java中实现多线程有两种方法:第一种方法是继承Thread
类,
覆盖方法run()。即创建Thread类的子类并重写run()方法,加入线程所要执行的代码即可。种方法简单明了,但是它有一个很大的缺点,就是一个 ...
在利用Hibernate开发DAO模块时,我们和Session打的交道最多,所以如何合理的管理Session,避免Session的频繁创建和销
毁,对于提高系统的性能来说是非常重要的,以往是通过eclipse的插件来自动完成这些代码的,当然效果是不错的,但是总是觉得不爽(没有读懂那些冗长
的代码),所以现在打算自己实现Session管理的代码。我们知道Session是由SessionFactory负责创建的,而
SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一个SessionFactory并从 ...
ThreadLocal的几种误区
最近由于需要用到ThreadLocal,在网上搜索了一些相关资料,发现对ThreadLocal经常会有下面几种误解
一、ThreadLocal是java线程的一个实现
ThreadLocal的确是和java线程有关,不过它并不是java线程的一个实现,它只是用来维护本地变量。针对每个线程,提供自己的变量版本,主要是为了避免线程冲突,每个线程维护自己的版本。彼此独立,修改不会影响到对方。
二、ThreadLocal是相对于每个s ...
早在Java
1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新的选择。使用
这个工具类可以很简洁地编写出优美的多线程程序,虽然ThreadLocal非常有用,但是似乎现在了解它、使用它的朋友还不多。
ThreadLocal是什么
ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread
local
variable(线程局部变量)。也许把它命名为ThreadL ...
线程封闭
新一篇: 线程安全
function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+e ...
Java 理论和实践:
安全构造技术
在构造期间,不要让“this”引用逃脱
<!--
document.write('<tr valign="top"><td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height= ...
Java多核线程笔记-volatile的原理与技巧
volatile, 用更低的代价替代同步
为什么
使用volatile比同步代价更低?
同步的代价, 主要由其覆盖范围决定, 如果可以降低同步的覆盖范围, 则可以大幅提升程序性能.
而volatile的覆盖范围仅仅变量级别的. 因此它的同步代价很低.
volatile原理是什么?
volatile的语义, 其实是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我.(工作内存详见java内存模型)
因此, 当多核或多线程在访问该变量时, ...
JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放数据
栈区:
1.每个线程包含一个栈区,栈中只保存原始类型数据和对象和对象引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
方法区:
1.又叫静态 ...
1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
2.
栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共
享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要
在运行时动态分配内存,存取速度较慢。
3. Java中的数据类型有两种。
一种是基本类型(primitive
t ...
- 浏览: 8592 次
- 性别:

- 来自: 广州

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
java中堆和堆栈的区别
引用[u][/u][i][/i][b][/b][img][/img][url ...
-- by yinguohui -
阻塞I/O,非阻塞I/O
1、异步与同步的区别:异步不会引起request进程阻塞。而同步会。2、阻塞IO ...
-- by jokermanager -
阻塞I/O,非阻塞I/O
两个问题: 1. "read操作是否阻塞,阻塞I/O是阻塞的,而异步I ...
-- by FGhost






评论排行榜