java语言高级特性(一)多线程创建、交互

创建线程的两种常用方法

第一种是继承Thread类,重写该类的run()方法。
第二种 方式实现Runnable接口,并重写该接口的run()方法。

线程池

jdk1.5以前需要考虑 线程的创建 结束和 结果的获取 等诸多细节不仅如此,使用newThread( )方式定义线程,在时间和 空间效率方面都存在不足。

ExcuteServices excutor=Excutors.newCacheThreadPool();
System.out.print("all task submitted")
for(int i=0;i<5;i++){
  excutor.submit(New Processor(i));
 }
 excutor.shutdown;
 excutor.awaitTermination(1,TimeUtil.DAYS);
 System.out.print("all task completed")

上述程序创建了一个可缓存线程池 ( CacheThreadPool):只需通过循环的方式, 便可把想要完成的任务数量传递给线程池, 线程池会创建尽可能多的必须线程来并行执。一旦前面的线程执束后可以被重复使用。
除了可缓存线程池 (CacheThreadPool),定长线(fixThreadPool),可 以创 建 固定数 量 的线程在线程都被使用之后, 后续 申请使用 的线程都会 被 阻 塞。
如果我们将上述代码中的newCachedThreadPool()改为newFixedThreadPool(2),括号中的字2, 表示创建了两个线程,下面 的代码不变, 则相等于 把 5 个任两个线程来完成。这就意味着,每一个线程完成 一次任务后, 并不会就此消逝, 而是继续完成剩下的任务, 直到所有任务完成。
可见程池确实简化了线程的管理, 提升了线程的执行效能.

Semaphore和CountDownLatch强化了对多线程并发控制能力,简化了控制线程间协调合作的方法。

信号量Semaphore

信号量 (Semaphore), 有时被称为信号灯,它负责协调各个线程, 以保证 它们能够正确、 合理的使用公共资源。 信号量可 以控制某个资源可被 同时访 问 的个数, 拿到信号量 的线程可 以进人代码,否则就等待,通过acquare()和 release ()获取和释放访问许可。

闭锁(CountDownLatch)

闭锁(CountDownLatch)是一个并发构造,它允许一个或多个线程等待一系列制定操作的完成。闭锁(CountDownLatch)以一个给定的计数初始化,每调用一次countDown(),这一数量就减一,然后通过调用await()方法,将阻塞线程,使其等待直到计数达到零。

阻塞队列(BlockingQueue)

为了解决多线程访问共享数据时造成的数据访问冲突问题,提供了具有多个具有线程安全性的类。

在闭锁中,对象latch没有使用synchronized关键字锁定,但线程访问不会冲突。除了CountDownLatch以外,阻塞队列(BlockingQueue)的线程安全性也为开发并发程序带来了极大方便。

private static BlockingQueue<Integer>queue=
new ArrayBlockingQueue<Integer>(10);
queue.put();//product
queue.take();//consumer

重入锁(Re-entrantlock)

针对并发程序可能引起的死锁问题给出了更为便捷的解决方案。

解决线程同时获取多个互斥锁顺序不同,可能引发的死锁(DeadLock)现象。
当需要加一个以上的互斥锁时,使用Reentrant lock避免了像synchronized语句块一样的嵌套。更重要的是,reentrant lock有tryLock()功能,可使得当获取到一个互斥锁时,另一个获取失败的情况下,放弃已获取到的互斥锁。这就巧妙的避免了死锁现象的出现。

private static Lock lockn=new ReentrantLock();
try{
booleanObjectn =lockn.tryLock();//尝试获取锁
booleanObjectn =lockn.tryLock();//获取第二个锁
}finally{
  if(booleanObjectn)return;
  if(booleanObjectn)lockn.unlock();
}

猜你喜欢

转载自blog.csdn.net/qq_37804737/article/details/78040505