本文目录一览:
- 1、java并发包有哪些类
- 2、求java并发编程的实例 java多线程编程例子
- 3、java 并发实现原理: 是否可以利用多线程,实现10个并发执行 请给个例子(java代码),非常感谢!!!!
- 4、java并发框架有哪些
- 5、电脑培训分享Java 并发编程:核心理论
- 6、「多线程」额外的并发工具类
java并发包有哪些类
1、CyclicBarrier
一个同步辅助类,允许一组线程相互等待,直到这组线程都到达某个公共屏障点。该barrier在释放等待线程后可以重用,因此称为循环的barrier。
来个示例:
[java] view plain copy
package test;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Recipes_CyclicBarrier {
public static CyclicBarrier barrier = new CyclicBarrier(10);
public static void main(String[] args){
ExecutorService executor = Executors.newCachedThreadPool();//FixedThreadPool(10);
for(int i=1;i=10;i++){
executor.submit(new Thread(new Runner(i+"号选手")));
}
executor.shutdown();
}
}
class Runner implements Runnable{
private String name;
public Runner(String name){
this.name = name;
}
@Override
public void run() {
System.out.println(name + "准备好了。");
try {
Recipes_CyclicBarrier.barrier.await(); //此处就是公共屏障点,所有线程到达之后,会释放所有等待的线程
} catch (Exception e) {
}
System.out.println(name + "起跑!");
}
}
2、CountDownLatch
CountDownLatch和CyclicBarrier有点类似,但是还是有些区别的。CountDownLatch也是一个同步辅助类,它允许一个或者多个线程一直等待,直到正在其他线程中执行的操作完成。它是等待正在其他线程中执行的操作,并不是线程之间相互等待。CountDownLatch初始化时需要给定一个计数值,每个线程执行完之后,必须调用countDown()方法使计数值减1,直到计数值为0,此时等待的线程才会释放。
来个示例:
[java] view plain copy
package test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo {
public static CountDownLatch countDownLatch = new CountDownLatch(10);//初始化计数值
public static void main(String[] args){
ExecutorService executor = Executors.newCachedThreadPool();//FixedThreadPool(10);
for(int i=1;i=10;i++){
executor.submit(new Thread(new Runner1(i+"号选手")));
}
executor.shutdown();
}
}
class Runner1 implements Runnable{
private String name;
public Runner1(String name){
this.name = name;
}
@Override
public void run() {
System.out.println(name + "准备好了。");
CountDownLatchDemo.countDownLatch.countDown(); //计数值减1
try {
CountDownLatchDemo.countDownLatch.await();
} catch (Exception e) {
}
System.out.println(name + "起跑!");
}
}
3、CopyOnWriteArrayList CopyOnWriteArraySet
CopyOnWriteArrayList CopyOnWriteArraySet是并发容器,适合读多写少的场景,如网站的黑白名单设置。缺点是内存占用大,数据一致性的问题,CopyOnWrite容器只能保证数据最终的一致性,不能保证数据实时一致性。鉴于它的这些缺点,可以使用ConcurrentHashMap容器。
实现原理:新增到容器的数据会放到一个新的容器中,然后将原容器的引用指向新容器,旧容器也会存在,因此会有两个容器占用内存。我们也可以用同样的方式实现自己的CopyOnWriteMap。
4、ConcurrentHashMap
ConcurrentHashMap同样是一个并发容器,将同步粒度最小化。
实现原理:ConcurrentHashMap默认是由16个Segment组成,每个Segment由多个Hashtable组成,数据变更需要经过两次哈希算法,第一次哈希定位到Segment,第二次哈希定位到Segment下的Hashtable,容器只会将单个Segment锁住,然后操作Segment下的Hashtable,多个Segment之间不受影响。如果需要扩容不是对Segment扩容而是对Segment下的Hashtable扩容。虽然经过两次哈希算法会使效率降低,但是比锁住整个容器效率要高得多。
5、BlockingQueue
BlockingQueue只是一个接口,它的实现类有ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、DelayQueue、LinkedBlockingDeque。
ArrayBlockingQueue:由数据支持的有界阻塞队列。
LinkedBlockingQueue:基于链接节点、范围任意的阻塞队列。
PriorityBlockingQueue:无界阻塞队列。
SynchronousQueue:一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作。
DelayQueue:Delayed元素的一个无界阻塞队列。
LinkedBlockingDeque:基于链接节点、范围任意的双端阻塞队列,可以在队列的两端添加、移除元素。
6、Lock
Lock分为公平锁和非公平锁,默认是非公平锁。实现类有ReetrantLock、ReetrantReadWriteLock,都依赖于AbstractQueuedSynchronizer抽象类。ReetrantLock将所有Lock接口的操作都委派到Sync类上,Sync有两个子类:NonFairSync和FaiSync,通过其命名就能知道分别处理非公平锁和公平锁的。AbstractQueuedSynchronizer把所有请求构成一个CLH队列,这里是一个虚拟队列,当有线程竞争锁时,该线程会首先尝试是否能获取锁,这种做法对于在队列中等待的线程来说是非公平的,如果有线程正在Running,那么通过循环的CAS操作将此线程增加到队尾,直至添加成功。
7、Atomic包
Atomic包下的类实现了原子操作,有对基本类型如int、long、boolean实现原子操作的类:AtomicInteger、AtomicLong、AtomicBoolean,如果需要对一个对象进行原子操作,也有对对象引用进行原子操作的AtomicReference类,还有对对象数组操作的原子类:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。原子操作核心思想是CAS操作,然后调用底层操作系统指令来实现。
求java并发编程的实例 java多线程编程例子
不懂……如果你是用线程同时去添加多个用户,第一,人不是多线程的,你只能一个个去添加;第二,如果你想添加用户的时候还没有添加完成又做别的事情,完成可能用面向对象思想,程序一块块执行的,对于编人员来说不用考虑到多线程,程序本身已经完成了,比如我点击了添加用户的按钮,你的程序还可以往下跑,因为你仅仅是new了一个添加用户的窗口,主程序可以继续向下执行,除非你玩模态对话;第三,如果你非要多线程添加用户,就用简单的线程例子能解决啊,public void run(){}方法里写上添加用户的代码就行啦,主程序运行时new 你写好的线程类(YouThread implements Runnable{public void run(...)}),启动它(new Thread(new YouThread()).start());之后写上自己要继续执行的代码
java 并发实现原理: 是否可以利用多线程,实现10个并发执行 请给个例子(java代码),非常感谢!!!!
public static void main(String[] args) {
for(Thread t:getThreads()){
t.start();
}
}
public static Thread[] getThreads(){
Thread[] thread = new Thread[10];
for(int i=0;i10;i++){
final Integer num = new Integer(i);
thread[i] = new Thread(new Runnable(){
public void run() {
int j=5;
while(j--0){
System.out.println("this is thread"+num);
}
}
});
}
return thread;
}
java并发框架有哪些
Java并发框架java.util.concurrent是JDK5中引入到标准库中的(采用的是Doug
Lea的并发库)。该包下的类可以分为这么块:
Executors
1)接口:
Executor(例子涉及):用来执行提交的Runnable任务的对象。是一个简单的标准化接口,用来定义包括线程池、异步IO、轻量级任务框架等等。任务可以由一个新创建的线程、一个已有任务执行线程、或是线程直接调用execute()来执行,可以串行也可并行执行,取决于使用的是哪个Executor具体类。
ExecutorService(例子涉及):Executor的子接口,提供了一个更加具体的异步任务执行框架:提供了管理结束的方法,以及能够产生Future以跟踪异步任务进程的方法。一个ExcutorService管理着任务队列和任务调度。
ScheduledExecutorService(例子涉及):ExecutorService的子接口,增加了对延迟和定期任务执行的支持。
Callable(例子涉及):一个返回结果或抛出异常的任务,实现类需要实现其中一个没有参数的叫做call的方法。Callabe类似于Runnable,但是Runnable不返回结果且不能抛出checked
exception。ExecutorService提供了安排Callable异步执行的方法。
Future(例子涉及):代表一个异步计算的结果(由于是并发执行,结果可以在一段时间后才计算完成,其名字可能也就是代表这个意思吧),提供了可判断执行是否完成以及取消执行的方法。
2)实现:
ThreadPoolExecutor和ScheduledThreadPoolExecutor:可配置线程池(后者具备延迟或定期调度功能)。
Executors(例子涉及):提供Executor、ExecutorService、ScheduledExecutorService、ThreadFactory以及Callable的工厂方法及工具方法。
FutureTask:对Future的实现
ExecutorCompletionService(例子涉及):帮助协调若干(成组)异步任务的处理。
Queues
非阻塞队列:ConcurrentLinkedQueue类提供了一个高效可伸缩线程安全非阻塞FIFO队列。
阻塞队列:BlockingQueue接口,有五个实现类:LinkedBlockingQueue(例子涉及)、ArrayBlockingQueue、SynchronousQueue、PriorityBlockingQueue和DelayQueue。他们对应了不同的应用环境:生产者/消费者、消息发送、并发任务、以及相关并发设计。
Timing
TimeUnit类(例子涉及):提供了多种时间粒度(包括纳秒)用以表述和控制基于超时的操作。
Synchronizers 提供特定用途同步语境
Semaphore(例子涉及):计数信号量,这是一种经典的并发工具。
CountDownLatch(例子涉及):简单的倒计数同步工具,可以让一个或多个线程等待直到另外一些线程中的一组操作处理完成。
CyclicBarrier(例子涉及):可重置的多路同步工具,可重复使用(CountDownLatch是不能重复使用的)。
Exchanger:允许两个线程在汇合点交换对象,在一些pipeline设计中非常有用。
Concurrent Collections
除队列外,该包还提供了一些为多线程上下文设计的集合实现:ConcurrentHashMap、CopyOnWriteArrayList及CopyOnWriteArraySet。
注意:"Concurrent"前缀的类有别于"synchronized"前缀的类。“concurrent”集合是线程安全的,不需要由单排斥锁控制的(无锁的)。以ConcurrentHashMap为例,允许任何数量的并发读及可调数量的并发写。“Synchronized”类则一般通过一个单锁来防止对集合的所有访问,开销大且伸缩性差。
电脑培训分享Java 并发编程:核心理论
并发编程是Java程序员最重要的技能之一,也是最难掌握的一种技能。它要求编程者对计算机最底层的运作原理有深刻的理解,同时要求编程者逻辑清晰、思维缜密,这样才能写出高效、安全、可靠的多线程并发程序。电脑培训发现本系列会从线程间协调的方式(wait、notify、notifyAll)、Synchronized及Volatile的本质入手,详细解释JDK为我们提供的每种并发工具和底层实现机制。在此基础上,我们会进一步分析java.util.concurrent包的工具类,包括其使用方式、实现源码及其背后的原理。本文是该系列的第一篇文章,是这系列中最核心的理论部分,之后的文章都会以此为基础来分析和解释。
关于java并发编程及实现原理,还可以查阅《Java并发编程:Synchronized及其实现原理》。
一、共享性
数据共享性是线程安全的主要原因之一。如果所有的数据只是在线程内有效,那就不存在线程安全性问题,这也是我们在编程的时候经常不需要考虑线程安全的主要原因之一。但是,在多线程编程中,数据共享是不可避免的。最典型的场景是数据库中的数据,为了保证数据的一致性,我们通常需要共享同一个数据库中数据,即使是在主从的情况下,访问的也同一份数据,主从只是为了访问的效率和数据安全,而对同一份数据做的副本。我们现在,通过一个简单的示例来演示多线程下共享数据导致的问题。
二、互斥性
资源互斥是指同时只允许一个访问者对其进行访问,具有唯一性和排它性。我们通常允许多个线程同时对数据进行读操作,但同一时间内只允许一个线程对数据进行写操作。所以我们通常将锁分为共享锁和排它锁,也叫做读锁和写锁。如果资源不具有互斥性,即使是共享资源,我们也不需要担心线程安全。例如,对于不可变的数据共享,所有线程都只能对其进行读操作,所以不用考虑线程安全问题。但是对共享数据的写操作,一般就需要保证互斥性,上述例子中就是因为没有保证互斥性才导致数据的修改产生问题。
「多线程」额外的并发工具类
Java的结合框架提供了位于java.util包下的诸多接口和类。其中接口包括了List、Set 和 Map。类包括 ArrayList、TreeMap 和 HashMap。 ArrayList、TreeMap 和 HashMap 以及实现类这些接口的类都不是线程安全的。不过你可以使用类java.util.Collections中的同步包装方法 让他们变得安全。举个栗子,可以向Collections.synchronizedList()中传入一个ArrayList实例,已获得一个线程安全的ArrayList。
线程安全的集合存在的问题:
那怎么办呢?使用并发工具类
并发工具类使用并发集合来应对这些问题,并发集合具有并发性能和高扩展行、面向集合的类型,他们存储在java.util.concurrent 包中,面向结合的类返回了弱一致性的迭代器
弱一致性迭代器具有的属性
前面我们通过wait() 和 notify()实现了生产者-消费者应用, 有了 BlockingQueue 其实代码可以更简单。
如果发现打印顺序错乱,别忘了使用 synchronized 或者 lock/unlock 来同步代码块。
类 ConcurrentHashMap 和 HashMap 在行为上没啥区别,但无需显示同步就可以工作于多条线程的上下文。
看个熟悉的列子:你经常需要检查一个 map 中是否包含某个特定的值,当这个值不存在的时候,将它放进 map 中;
乍一看没啥问题,但是放在多线程的环境中,他却不是线程安全的。 map.containsKey()和 map.put() 方法之间,其他线程可能插入了这个条目,很可能会被覆盖掉。 为了消除这个竞态条件,你必须显示的同步这段代码
上面synchronized这段代码保证了可见性,但是在线程高争用环境下影响性能,还可能发生死锁之类的活跃性问题。 那如何用原子变量来代替synchronized关键字呢?看下面的例子
Java低级的同步机制,强制使用互斥以及可见性,以如下的方式影响了硬件的使用和扩展能力。
你会认为 volatile 是同步的备胎,但 volatile 变量也只能解决可见性问题,无法应用于安全的实现原子的 读-改-写 的序列。这个原子的序列对于 实现线程安全的计数器以及其他需要互斥访问的实体是需要的。并发工具集提供了另一个备胎,即 compare-and-swap。
Compare-and-swap(CAS) 是针对非抢占式微处理器的一条指令的宽泛术语。这条指令读取内存的位置, 比较读到的值和期望的值,当读到的值和期望的值匹配时,就将期望的值存储到该内存的位置;否则什么事也不会发生。 现代微处理提供了多种 CAS 的变体, CAS 支持 读-改-写 的序列 1,从地址 A 读出值 x; 2,在 x 上进行一个多步计算,衍生出一个新值 y; 3,使用 CAS 把 A 的值从 x 改成 y。当操作这些步骤时,如果 A 的值没有发生改变,CAS 就成功了。
最终,JDK通过CPU的cmpxchgl指令的支持,实现AtomicInteger的CAS操作的原子性。
public ForkJoinPool() 以 Runtime.getRuntime().availableProcessors()的返回值作为 parallelism 来创建 ForkJoinPool
看代码更亲切