JAVA并发包备忘录

 


JAVA并发包的功能主要包含:

1)原子操作类,诸如AtomicInteger、AtomicLong等类;

2)并发集合类,如ArrayBlockingQueue、ConcurrentMapCopyOnWriteArrayList

3)锁机制,比synchronized性能更优的锁机制,

boolean captured = lock.tryLock();
		try {
			System.out.println("tryLock:" + captured);
		} finally {
			if (captured)
				lock.unlock();
		}


4)线程池,newCachedThreadPool,newFixedThreadPool(5),newSingleThreadExecutor()等

5)工具类:

       CountDownLatch:在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待

//一个CountDouwnLatch实例是不能重复使用的,也就是说它是一次性的,锁一经被打开就不能再关闭使用了,如果想重复使用,请考虑使用CyclicBarrier。
public class CountDownLatchTest {

 // 模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。
 public static void main(String[] args) throws InterruptedException {

     // 开始的倒数锁 
     final CountDownLatch begin = new CountDownLatch(1);  

     // 结束的倒数锁 
     final CountDownLatch end = new CountDownLatch(10);  

     // 十名选手 
     final ExecutorService exec = Executors.newFixedThreadPool(10);  

     for (int index = 0; index < 10; index++) {
         final int NO = index + 1;  
         Runnable run = new Runnable() {
             public void run() {  
                 try {  
                     // 如果当前计数为零,则此方法立即返回。
                     // 等待
                     begin.await();  
                     Thread.sleep((long) (Math.random() * 10000));  
                     System.out.println("No." + NO + " arrived");  
                 } catch (InterruptedException e) {  
                 } finally {  
                     // 每个选手到达终点时,end就减一
                     end.countDown();
                 }  
             }  
         };  
         exec.submit(run);
     }  
     System.out.println("Game Start");  
     // begin减一,开始游戏
     begin.countDown();  
     // 等待end变为0,即所有选手到达终点
     end.await();  
     System.out.println("Game Over");  
     exec.shutdown();  
 }
}


cyclicBarrier:与countDownLoatch相似,只不过countDownLoatch只能执行一次,而cyclicBarrier可以执行多次

/**
 * 与countDownLoatch相似,只不过countDownLoatch只能执行一次,而cyclicBarrier可以执行多次
 * 
 * //设置parties、count及barrierCommand属性。 <br/>
 * CyclicBarrier(int): <br/>
 * <br/>
 * //当await的数量到达了设定的数量后,首先执行该Runnable对象。<br/>
 * CyclicBarrier(int,Runnable):<br/>
 * <br/>
 * //通知barrier已完成线程 <br/>
 * await(): <br/>
 * getNumberWaiting():返回当前正在等待的线程数量。
 * 
 * @author wull
 * 
 */
public class CyclicBarrierTest {
	public static void main(String[] args) {
		ExecutorService service = Executors.newCachedThreadPool();
		final CyclicBarrier cb = new CyclicBarrier(3); // 三个线程同时到达
		for (int i = 0; i < 3; i++) {
			Runnable runnable = new Runnable() {
				public void run() {
					try {
						Thread.sleep((long) (Math.random() * 10000));
						System.out.println("线程"
								+ Thread.currentThread().getName()
								+ "即将到达集合地点1,当前已有"
								+ (cb.getNumberWaiting() + 1)
								+ "个已到达"
								+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊"
										: "正在等候"));
						try {
							cb.await();
						} catch (BrokenBarrierException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						Thread.sleep((long) (Math.random() * 10000));
						System.out.println("线程"
								+ Thread.currentThread().getName()
								+ "即将到达集合地点2,当前已有"
								+ (cb.getNumberWaiting() + 1)
								+ "个已到达"
								+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊"
										: "正在等候"));
						try {
							cb.await();
						} catch (BrokenBarrierException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						Thread.sleep((long) (Math.random() * 10000));
						System.out.println("线程"
								+ Thread.currentThread().getName()
								+ "即将到达集合地点3,当前已有"
								+ (cb.getNumberWaiting() + 1)
								+ "个已到达"
								+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊"
										: "正在等候"));
						try {
							cb.await();
						} catch (BrokenBarrierException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
			service.execute(runnable);
		}
		service.shutdown();
	}
}


Exchanger:提供了一个同步点,在这个同步点,一对线程可以交换数据

/**
 * 类java.util.concurrent.Exchanger提供了一个同步点,在这个同步点,一对线程可以交换数据。<br/>
 * 每个线程通过exchange()方法的入口提供数据给他的伙伴线程,并接收他的伙伴线程提供的数据,并返回。<br/>
 * 当两个线程通过Exchanger交换了对象,这个交换对于两个线程来说都是安全的。 <br/>
 * 
 * @author wull
 * 
 */
public class ExchangerDemo {
	public static void main(String args[]) {
		Exchanger<String> exgr = new Exchanger<String>();

		new UseString(exgr);
		new MakeString(exgr);
	}
}

class MakeString implements Runnable {
	Exchanger<String> ex;
	String str;
	MakeString(Exchanger<String> c) {
		ex = c;
		str = new String();

		new Thread(this).start();
	}

	public void run() {
		char ch = 'A';
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 5; j++)
				str += (char) ch++;
			try {
				str = ex.exchange(str);
				System.out.println("RECIEVE:"+str);
			} catch (InterruptedException exc) {
				System.out.println(exc);
			}
		}
	}
}

class UseString implements Runnable {
	Exchanger<String> ex;
	String str;
	UseString(Exchanger<String> c) {
		ex = c;
		new Thread(this).start();
	}

	public void run() {
		for (int i = 0; i < 3; i++) {
			try {
				str = ex.exchange(new String());
				System.out.println("Got: " + str);
			} catch (InterruptedException exc) {
				System.out.println(exc);
			}
		}
	}
}


SemaphoreSemaphore:相当于一个锁,这个锁同时可以被N个线程所使用,第N+1个线程处于等待状态

public class SemaphoreDemo {
	public static void main(String[] args) {

		// 线程池
		ExecutorService exec = Executors.newCachedThreadPool();

		// 只能5个线程同时访问
		final Semaphore semp = new Semaphore(5);

		// 模拟20个客户端访问
		for (int index = 0; index < 20; index++) {
			final int NO = index;
			Runnable run = new Runnable() {
				public void run() {
					try {
						// 获取许可
						semp.acquire();
						System.out.println("Accessing: " + NO);
						Thread.sleep((long) (Math.random() * 10000));

						// 访问完后,释放
						semp.release();

						System.out.println("-----------------"
								+ semp.availablePermits());
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			};
			exec.execute(run);
		}

		// 退出线程池
		exec.shutdown();

	}
}


6)Callable和Future

一个有返回值的线程Runnable

 

7)Fork-join框架

这是一个JDK7引入的并行框架,它把流程划分成fork(分解)+join(合并)两个步骤(怎么那么像MapReduce?),传统线程池来实现一个并行任务的时候,经常需要花费大量的时间去等待其他线程执行任务的完成,但是fork-join框架使用work stealing技术缓解了这个问题:

  1. 每个工作线程都有一个双端队列,当分给每个任务一个线程去执行的时候,这个任务会放到这个队列的头部;
  2. 当这个任务执行完毕,需要和另外一个任务的结果执行合并操作,可是那个任务却没有执行的时候,不会干等,而是把另一个任务放到队列的头部去,让它尽快执行;
  3. 当工作线程的队列为空,它会尝试从其他线程的队列尾部偷一个任务过来;
  4. 取得的任务可以被进一步分解。
  • ForkJoinPool.class,ForkJoin框架的任务池,ExecutorService的实现类
  • ForkJoinTask.class,Future的子类,框架任务的抽象
  • ForkJoinWorkerThread.class,工作线程
  • RecursiveTask.class,ForkJoinTask的实现类,compute方法有返回值,下文中有例子
  • RecursiveAction.class,ForkJoinTask的实现类,compute方法无返回值,只需要覆写compute方法,对于可继续分解的子任务,调用coInvoke方法完成(参数是RecursiveAction子类对象的可变数组):

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值