Java中同步与并发的运用

发布时间:2024-02-24 18:12:08

1.同步容器类包括两部分:vector和hashtable

另一类是同步包装类,由Collections.synchronizedXXX创建。同步容器对容器的所有状态进行串行访问,从而实现线程安全。

它们存在如下问题:

a)对于符合*作,需要额外的锁保护。比如迭代,缺少则添加等条件运算。

b)toString,hashCode,equals都会间接的调用迭代,都需要注意并发。

2.java5.0中的并发容器。

ConcurrentHashMap可以替代同步Map实现。

当主要为读*作时,CopyOnWriteArrayList是List的同步实现。

同时,增加了Queue和BlockingQueue:ConcurentLinkedQueue:FIFO队列。

PriorityQueue:非并发的优先级顺序队列。

BlockingQueue则增加了可阻塞的*和获取。

a)ConcurentHashMap:不是使用一个公共锁,而是分离锁。任意数量的读线程可以并发访问map,读者和写者也可以并发访问Map,并且有限数量的写还可以并发修改Map。但是,size和isEmpty语言被弱化,是估算值。

b)CopyOnWriteArrayList:迭代器保留一个底层基础数组引用,改引用不会修改。

3.Synchronizer

a)闭锁(CountDownLatch)。构造函数参数为n,通过countDown,n为0后,所有await的线程继续执行。

b)FutureTask:计算由Callable实现,可以携带结果的Runnable。包括:等待,运行和完成。

c)Semaphore:控制能够同时访问的活动数量

d)CyclicBarrier:类似于闭锁。闭锁等待的是事件,关卡等待的是其他线程。初始n,Runnabler,n个线程都await(),当n个线程都执行完成后到达关卡时,r执行,关卡重置,n个线程继续。

第2篇:java并发编程参考

在Java5.0之前,只有synchronized(内置锁)和volatile.Java5.0后引入了显示锁ReentrantLock.

ReentrantLock概况

ReentrantLock是可重入的锁,它不同于内置锁,它在每次使用都需要显示的加锁和解锁,而且提供了更高级的特*:公平锁,定时锁,有条件锁,可轮询锁,可中断锁.可以有效避免死锁的活跃*问题.ReentrantLock实现了

Lock接口:

复制代码代码如下:

publicinterfaceLock{

//阻塞直到获得锁或者中断

voidlock();

//阻塞直到获得锁或者中断抛异常

voidlockInterruptibly()throwsInterruptedException;

//只有锁可用时才获得,否则直接返回

booleantryLock();

//只有锁在指定时间内可用时才获得,否则直接返回,中断时抛异常

booleantryLock(longtime,TimeUnitunit)throwsInterruptedException;

voidunlock();

//返回一个绑定在这个锁上的条件

ConditionnewCondition();

}

Lock使用

复制代码代码如下:

Locklock=newReentrantLock();

lock.lock();

try{

//更新对象状态

}finally{

//这里注意,一定要有finally代码块去解锁

//否则容易造成死锁等活跃*问题

lock.unlock();

}

ReentrantLock特*

轮询锁的和定时锁

可轮询和可定时的锁请求是通过tryLock()方法实现的,和无条件获取锁不一样.ReentrantLock可以有灵活的容错机制.死锁的很多情况是由于顺序锁引起的,不同线程在试图获得锁的时候阻塞,并且不释放自己已经持有的锁,最后造成死锁.tryLock()方法在试图获得锁的时候,如果该锁已经被其它线程持有,则按照设置方式立刻返回,而不是一直阻塞等下去,同时在返回后释放自己持有的锁.可以根据返回的结果进行重试或者取消,进而避免死锁的发生.

公平*

ReentrantLock构造函数中提供公平*锁和非公平锁(默认)两种选择。所谓公平锁,线程将按照他们发出请求的顺序来获取锁,不允许插队;但在非公平锁上,则允许插队:当一个线程发生获取锁的请求的时刻,如果这个锁是可用的,那这个线程将跳过所在队列里等待线程并获得锁。我们一般希望所有锁是非公平的。因为当执行加锁*作时,公平*将讲由于线程挂起和恢复线程时开销而极大的降低*能。考虑这么一种情况:A线程持有锁,B线程请求这个锁,因此B线程被挂起;A线程释放这个锁时,B线程将被唤醒,因此再次尝试获取锁;与此同时,C线程也请求获取这个锁,那么C线程很可能在B线程被完全唤醒之前获得、使用以及释放这个锁。这是种双赢的局面,B获取锁的时刻(B被唤醒后才能获取锁)并没有推迟,C更早地获取了锁,并且吞吐量也获得了提高。在大多数情况下,非公平锁的*能要高于公平锁的*能。

可中断获锁获取*作

lockInterruptibly方法能够在获取锁的同时保持对中断的响应,因此无需创建其它类型的不可中断阻塞*作。

读写锁ReadWriteLock

ReentrantLock是一种标准的互斥锁,每次最多只有一个线程能持有锁。读写锁不一样,暴露了两个Lock对象,其中一个用于读*作,而另外一个用于写*作。

复制代码代码如下:

publicinterfaceReadWriteLock{

LockreadLock();

LockwriteLock();

}

可选择实现:

1.释放优先

2.读线程插队

3.重入*

4.降级

5.升级

ReentrantReadWriteLock实现了ReadWriteLock接口,构造器提供了公平锁和非公平锁两种创建方式。读写锁适用于读多写少的情况,可以实现更好的并发*。

示例

复制代码代码如下:

publicclassReadWriteMap{

privateMapmap;

privatefinalReadWriteLocklock=newReentrantReadWriteLock();

privatefinalLockreadLock=lock.readLock();

privatefinalLockwriteLock=lock.writeLock();

publicReadWriteMap(Mapmap){

this.map=map;

}

publicVget(Kkey){

readLock.lock();

try{

returnmap.get(key);

}finally{

readLock.unlock();

}

}

publicvoidput(Kkey,Vvalue){

writeLock.lock();

try{

map.put(key,value);

}finally{

writeLock.unlock();

}

}

}

第3篇:Java程序开发与运行环境

引导语:运行环境指一种把半编译的运行码在目标机器上运行的环境。以下是百分网小编分享给大家的Java程序开发与运行环境,欢迎阅读学习!

1.1JDK环境

Java不仅提供了一个丰富的语言和运行环境,而且还提供了一个免费的Java开发工具集(JavaDevelopersKits,简称JDK)。编程人员和最终用户可以利用这些工具来开发java程序或调用Java内容。JDK包括以下工具:javacJava语言编译器,输出结果为Java字节码javaJava字节码解释器javapDisassembeler:Java字节码分解程序,本程序返回Java程序的成员变量及方法等信息。javaprof资源分析工具,用于分析Java程序在运行过程中调用了哪些资源,包括类和方法的调用次数和时间,以及各数据类型的内存使用情况等。javahC代码处理工具,用于从Java类调用C++代码javaAppletViewer小应用程序浏览工具,用于测试并运行Java小应用程序javaDebuggerAPIJava调试工具APIPrototypeDebuggerJava调试工具原型Java开发环境还包括Java类库(包括I/O类库、用户界面类库、网络类库等)和HotJavaWWW浏览器。其中,HotJava浏览器提供了在WWW环境下运行Java代码的一个运行系统,而且还为WWW开发人员提供了一个Java开发框架。Java解释器是面向Java程序的一个*运行系统,它可以一种稳定、高*能方式运行那些*于平台的Java字节码,Java编译器则用于生成这些字节码。

1.1.1Java程序的编译

Java程序的编译程序是javac.exe。javac命令将Java程序编译成字节码,然后你可用java解释器java命令来解释执行这些Java字节码。Java程序源码必须存放在后缀为.java的文件里。Java程序里的每一个类,javac都将生成与类相同名称但后缀为.class文件。编译器把.class文件放在.java文件的同一个目录里,除非你用了-d选项。当你引用到某些自己定义的类时,必须指明它们的存放目录,这就需要利用环境变量参数CLASSPATH。环境变量CLASSPATH是由一些被分号隔开的路径名组成。如果传递给javac编译器的源文件里引用到的类定义在本文件和传递的其它文件中找不到,则编译器会按CLASSPATH定义的路径来搜索。例如:CLASSPATH=.;C:\\java\\classes则编译器先搜索当前目录,如果没搜索到,则继续搜索C:\\java\\classes目录。注意,系统总是将系统类的目录缺省地加在CLASSPATH后面,除非你用-classpath选项来编译。javac_g是一个用于调试的未优化的编译器,功能与用法和javac一样。javac的用法如下:javac[-g][-O][-debug][-depend][-nowarn][-verbose][-classpathpath][-nowrite][-ddir]file.java...以下是每个选项的解释。

选项解释:

-classpathpath定义javac搜索类的路径。它将覆盖缺省的CLASSPATH环境变量的设置。路径是由一些由逗号隔开的路径名组成,一般格式如下:.;例如:.;C:\\java\\doc\\classes;C:\\tools\\java\\classes表示编译器遇到一个新类,它先在本文件中查找它的定义,如果没有,则在本文件所处目录下其它文件中查找它的定义,如果还没有,则继续搜索C:\\java\\doc\\classes目录中的所有文件,以此类推。

-ddirectory指明类层次的根目录,格式如下:javac-dMyProgram.java这样将MyProgram.java程序里的生产的.class文件存放在my_dir目录里.

-g带调试信息编译,调试信息包括行号与使用java调试工具时用到的局部变量信息。如果编译没有加上-O优化选项,只包含行号信息。

-nowarn关闭警告信息,编译器将不显示任何警告信息。

-O优化编译static,final,private函数,注意你的类文件可能更大。

-verbose让编译器与解释器显示被编译的源文件名和被加载的类名。

环境变量

CLASSPATH用来提?copy;给系统搜索用户定义的类的缺省路径。各路径由分号隔开,例如:.;C:\\java\\doc\\classes;C:\\tools\\java\\classes表示编译器遇到一个新类,它先在本文件中查找它的定义,如果没有,则在本文件所处目录下其它文件中查找它的定义,如果还没有,则继续搜索C:\\java\\doc\\classes目录中的所有文件,以此类推。

第4篇:Java程序开发与运行环境

引导语:运行环境指一种把半编译的运行码在目标机器上运行的环境。以下是百分网小编分享给大家的Java程序开发与运行环境,帮助大家学习Java,欢迎阅读学习!

1JDK环境

Java不仅提供了一个丰富的语言和运行环境,而且还提供了一个免费的Java开发工具集(JavaDevelopersKits,简称JDK)。编程人员和最终用户可以利用这些工具来开发java程序或调用Java内容。JDK包括以下工具:javacJava语言编译器,输出结果为Java字节码javaJava字节码解释器javapDisassembeler:Java字节码分解程序,本程序返回Java程序的成员变量及方法等信息。javaprof资源分析工具,用于分析Java程序在运行过程中调用了哪些资源,包括类和方法的调用次数和时间,以及各数据类型的内存使用情况等。javahC代码处理工具,用于从Java类调用C++代码javaAppletViewer小应用程序浏览工具,用于测试并运行Java小应用程序javaDebuggerAPIJava调试工具APIPrototypeDebuggerJava调试工具原型Java开发环境还包括Java类库(包括I/O类库、用户界面类库、网络类库等)和HotJavaWWW浏览器。其中,HotJava浏览器提供了在WWW环境下运行Java代码的一个运行系统,而且还为WWW开发人员提供了一个Java开发框架。Java解释器是面向Java程序的一个*运行系统,它可以一种稳定、高*能方式运行那些*于平台的Java字节码,Java编译器则用于生成这些字节码。

2Java程序的编译

Java程序的编译程序是javac.exe。javac命令将Java程序编译成字节码,然后你可用java解释器java命令来解释执行这些Java字节码。Java程序源码必须存放在后缀为.java的文件里。Java程序里的每一个类,javac都将生成与类相同名称但后缀为.class文件。编译器把.class文件放在.java文件的同一个目录里,除非你用了-d选项。当你引用到某些自己定义的类时,必须指明它们的存放目录,这就需要利用环境变量参数CLASSPATH。环境变量CLASSPATH是由一些被分号隔开的路径名组成。如果传递给javac编译器的源文件里引用到的类定义在本文件和传递的其它文件中找不到,则编译器会按CLASSPATH定义的路径来搜索。例如:CLASSPATH=.;C:\\java\\classes则编译器先搜索当前目录,如果没搜索到,则继续搜索C:\\java\\classes目录。注意,系统总是将系统类的目录缺省地加在CLASSPATH后面,除非你用-classpath选项来编译。javac_g是一个用于调试的未优化的编译器,功能与用法和javac一样。javac的用法如下:javac[-g][-O][-debug][-depend][-nowarn][-verbose][-classpathpath][-nowrite][-ddir]file.java...以下是每个选项的解释。

选项解释:

-classpathpath定义javac搜索类的路径。它将覆盖缺省的CLASSPATH环境变量的设置。路径是由一些由逗号隔开的路径名组成,一般格式如下:.;例如:.;C:\\java\\doc\\classes;C:\\tools\\java\\classes表示编译器遇到一个新类,它先在本文件中查找它的定义,如果没有,则在本文件所处目录下其它文件中查找它的定义,如果还没有,则继续搜索C:\\java\\doc\\classes目录中的所有文件,以此类推。

-ddirectory指明类层次的根目录,格式如下:javac-dMyProgram.java这样将MyProgram.java程序里的生产的.class文件存放在my_dir目录里.

-g带调试信息编译,调试信息包括行号与使用java调试工具时用到的局部变量信息。如果编译没有加上-O优化选项,只包含行号信息。

-nowarn关闭警告信息,编译器将不显示任何警告信息。

-O优化编译static,final,private函数,注意你的类文件可能更大。

-verbose让编译器与解释器显示被编译的源文件名和被加载的类名。

3环境变量

CLASSPATH用来提?copy;给系统搜索用户定义的类的缺省路径。各路径由分号隔开,例如:.;C:\\java\\doc\\classes;C:\\tools\\java\\classes表示编译器遇到一个新类,它先在本文件中查找它的定义,如果没有,则在本文件所处目录下其它文件中查找它的定义,如果还没有,则继续搜索C:\\java\\doc\\classes目录中的所有文件,以此类推。

第5篇:Java程序开发与运行环境

Java既支持各种层次的网络连接,又以Socket类支持可靠的流(stream)网络连接,所以用户可以产生分布式的客户机和服务器。下面是小编整理的关于Java程序开发与运行环境,希望大家认真阅读!

2.1JDK环境

Java不仅提供了一个丰富的语言和运行环境,而且还提供了一个免费的Java开发工具集(JavaDevelopersKits,简称JDK)。编程人员和最终用户可以利用这些工具来开发java程序或调用Java内容。JDK包括以下工具:javacJava语言编译器,输出结果为Java字节码javaJava字节码解释器javapDisassembeler:Java字节码分解程序,本程序返回Java程序的成员变量及方法等信息。javaprof资源分析工具,用于分析Java程序在运行过程中调用了哪些资源,包括类和方法的调用次数和时间,以及各数据类型的内存使用情况等。javahC代码处理工具,用于从Java类调用C++代码javaAppletViewer小应用程序浏览工具,用于测试并运行Java小应用程序javaDebuggerAPIJava调试工具APIPrototypeDebuggerJava调试工具原型Java开发环境还包括Java类库(包括I/O类库、用户界面类库、网络类库等)和HotJavaWWW浏览器。其中,HotJava浏览器提供了在WWW环境下运行Java代码的一个运行系统,而且还为WWW开发人员提供了一个Java开发框架。Java解释器是面向Java程序的一个*运行系统,它可以一种稳定、高*能方式运行那些*于平台的Java字节码,Java编译器则用于生成这些字节码。

2.1.1Java程序的编译

Java程序的编译程序是javac.exe。javac命令将Java程序编译成字节码,然后你可用java解释器java命令来解释执行这些Java字节码。Java程序源码必须存放在后缀为.java的文件里。Java程序里的每一个类,javac都将生成与类相同名称但后缀为.class文件。编译器把.class文件放在.java文件的同一个目录里,除非你用了-d选项。当你引用到某些自己定义的类时,必须指明它们的存放目录,这就需要利用环境变量参数CLASSPATH。环境变量CLASSPATH是由一些被分号隔开的路径名组成。如果传递给javac编译器的源文件里引用到的类定义在本文件和传递的其它文件中找不到,则编译器会按CLASSPATH定义的路径来搜索。例如:CLASSPATH=.;C:\\java\\classes则编译器先搜索当前目录,如果没搜索到,则继续搜索C:\\java\\classes目录。注意,系统总是将系统类的目录缺省地加在CLASSPATH后面,除非你用-classpath选项来编译。javac_g是一个用于调试的未优化的编译器,功能与用法和javac一样。javac的用法如下:javac[-g][-O][-debug][-depend][-nowarn][-verbose][-classpathpath][-nowrite][-ddir]file.java...以下是每个选项的解释。

选项解释:

-classpathpath定义javac搜索类的路径。它将覆盖缺省的CLASSPATH环境变量的设置。路径是由一些由逗号隔开的路径名组成,一般格式如下:.;例如:.;C:\\java\\doc\\classes;C:\\tools\\java\\classes表示编译器遇到一个新类,它先在本文件中查找它的定义,如果没有,则在本文件所处目录下其它文件中查找它的定义,如果还没有,则继续搜索C:\\java\\doc\\classes目录中的所有文件,以此类推。

-ddirectory指明类层次的根目录,格式如下:javac-dMyProgram.java这样将MyProgram.java程序里的生产的.class文件存放在my_dir目录里.

-g带调试信息编译,调试信息包括行号与使用java调试工具时用到的局部变量信息。如果编译没有加上-O优化选项,只包含行号信息。

-nowarn关闭警告信息,编译器将不显示任何警告信息。

-O优化编译static,final,private函数,注意你的类文件可能更大。

-verbose让编译器与解释器显示被编译的源文件名和被加载的类名。

环境变量

CLASSPATH用来提?copy;给系统搜索用户定义的类的缺省路径。各路径由分号隔开,例如:.;C:\\java\\doc\\classes;C:\\tools\\java\\classes表示编译器遇到一个新类,它先在本文件中查找它的定义,如果没有,则在本文件所处目录下其它文件中查找它的定义,如果还没有,则继续搜索C:\\java\\doc\\classes目录中的所有文件,以此类推。

第6篇:java多线程的同步和异步

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java技术具有卓越的通用*、高效*、平台移植*和安全*,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网,同时拥有全球最大的开发者*社群。java多线程的同步和异步下面就分享给大家,欢迎大家阅读!

多线程和异步*作的异同

多线程和异步*作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应*。甚至有些时候我们就认为多线程和异步*作是等同的概念。但是,多线程和异步*作还是有一些区别的。而这些区别造成了使用多线程和异步*作的时机的区别。

异步*作的本质

所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步*作的本质,我们有必要了解一下它的硬件基础。熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。

DMA就是直接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知*作完成。这些无须消耗CPU时间的I/O*作正是异步*作的硬件基础。所以即使在DOS这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA*作。

线程的本质

线程不是一个计算机硬件的功能,而是*作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要*作系统投入CPU资源来运行和调度。

异步*作的优缺点

因为异步*作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少共享变量的数量),减少了死锁的可能。当然异步*作也并非完美无暇。编写异步*作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些初入,而且难以调试。

多线程的优缺点

多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。

适用范围

在了解了线程与异步*作各自的优缺点之后,我们可以来探讨一下线程和异步的合理用途。我认为:当需要执行I/O*作时,使用异步*作比使用线程+同步I/O*作更合适。I/O*作不仅包括了直接的文件、网络的读写,还包括数据库*作、WebService、HttpRequest以及Remoting等跨进程的调用。

而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O*作。这样在只有少数几个并发*作的时候还无伤大雅,如果需要处理大量的并发*作时就不合适了。

线程同步与异步区别

线程同步:是多个线程同时访问同一资源,等待资源访问结束,浪费时间,效率低

线程异步:访问资源时在空闲等待时同时访问其他资源,实现多线程机制

异步处理就是,你现在问我问题,我可以不回答你,等我有时间了再处理你这个问题.同步不就反之了,同步信息被立即处理--直到信息处理完成才返回消息句柄;异步信息收到后将在后台处理一段时间--而早在信息处理结束前就返回消息句柄