『Java』深入加强--线程并发库

Java5线程并发库讲解---截图标记笔记

 

java.util.concurrent.atomic 

类 AtomicIntegerFieldUpdater<T>-------------[对类中的基本数据等进行操作.

基于反射的实用工具,可以对指定类的指定 volatile int 字段进行原子更新。

 

 

 

线程并发库的应用

 

由tomcat原理引出线程池:

我们做一个tomcat服务器很难,难在于我们的性能提升不上去

 

 

 

 

Java5.0中提供的线程池[ThreadPool]


 

 

 

Shutdown:启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。

shutdownNow:试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。

 

 

 

package cn.itcast.extend.thread;
//java5线程并发库的应用-----线程池
//线程池中就两个东西:1,线程池中有几个线程  2,往里丢了几个任务			[将任务丢进去就ok了,不用去管,只要有空余线程就自动去接待任务]
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class ThreadPoolTest {
	public static void main(String[] args) {
	 //固定的线程池,自定义线程数量   ExecutorService threadPool=Executors.newFixedThreadPool(3);
	//动态的线程池,给几个任务,就自动创建几个线程   ExecutorService threadPool=Executors.newCachedThreadPool();
	
	ExecutorService threadPool=Executors.newSingleThreadExecutor();//建立一个单一线程池:好处,永远保证池子中有一个线程
	//可以实现线程死掉后又复活的现象.
	
		for(int i=1;i<=10;i++){
			final int task=i;
			threadPool.execute(new Runnable() {//往线程池中丢任务
			@Override
			public void run() {
				for(int i=1;i<=10;i++){
					try {
						Thread.sleep(20);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+" is looping of  "+i+" for task of "+task);
				}
			}	
		});
		//threadPool.shutdownNow();立即将线程池中的所有线程干掉.
				//会报异常----java.lang.InterruptedException: sleep interrupted
		}
		System.out.println("all of 10 tasks hava committed!");
		//threadPool.shutdown();//所有的任务都干完了.线程们都空闲了,就关掉池子,销毁池子中的所有线程
		
		
		
		
		
		//用线程池启动定时器------缺陷不能指定绝对的时间
		//解决缺陷的方法:date.getTime()-System.currentTimeMillis();
		
		ScheduledFuture s=Executors.newScheduledThreadPool(3).scheduleAtFixedRate(
				new Runnable() {//任务
					@Override
					public void run() {
						System.out.println("bombing!");
					}
				},
				3,//几秒后开炸
				2,//频率 
				TimeUnit.SECONDS//单位
				);
		
		//返回的ScheduledFuture对象中有个cancel方法,可以取消当前任务.
		//s.cancel(true);
	}
}

 

 

 

 

 

 

 

Callable与Future的应用

 

 

 

 

读写锁技术的妙用

 

 

 

package cn.itcast.extend.thread;

//java5的线程锁技术
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockTest {

	public static void main(String[] args) {
		LockTest TTS = new LockTest();
		TTS.init();
	}

	// 注意:静态方法中不能new内部类的对象,因为,内部类有一个特性,就是可以访问其外部类的成员变量.所以内部类
	// 中存在一个外部类的对象super,而静态方法中根本不存在对象.
	public void init() {
		final Outputer op = new Outputer();
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					op.output("zhangxiaoxiang");
				}
			}
		}).start();
		Thread thread1 = new Thread() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					op.output("lihuoming");
				}
			}
		};
		thread1.start();
	}

	static class Outputer {
		Lock lock = new ReentrantLock();

		public void output(String name) {
			lock.lock();// 加上锁
			try {
				for (int i = 0; i < name.length(); i++) {
					System.out.print(name.charAt(i));
				}
				System.out.println();
			} finally {
				lock.unlock();
			}
		}

	}

}

 

 

 

 

 

 

package cn.itcast.extend.thread;
//12_传智播客_张孝祥_java5读写锁技术的妙用[给力--文档上的案例很重要]

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;


		//----面试题:做一个缓存系统
public class CacheDemo {
	private Map<String,Object> cache=new HashMap<String, Object>(); 
	
	public static void main(String[] args) {
			
	}
	//缓存系统:检查内部是否有数据,如果有就直接给他,如果没有,就去数据库中找,找到后给他,并且,缓存起来备用.

	//运用读写锁---创建一个读写锁[多个并发的读,性能会提高]
	//多个数据来读的时候是并发的,不会造成对数据的破坏,所以,一开始加上读锁.
	//加入一个线程发现,内部没有数据,就将读锁关掉,挂上写锁.待写完数据后释放写锁,在激活读锁,实现并发读数据
	private ReadWriteLock rwl=new ReentrantReadWriteLock();
	
	public Object getData(String key){
		rwl.readLock().lock();		//读锁打开
		Object value=null;
		try{
			value=cache.get(key);
			if(value==null){
				rwl.readLock().unlock();//如果发现,该数据为空,就将读锁释放.
				rwl.writeLock().lock();//打开写锁.---避免在他写的时候,来添乱.
				try{
					if(value==null)
						value="实际是去queryDB()";
				}finally{
					rwl.writeLock().unlock();//写完后,就将写锁,释放.
				}
					rwl.readLock().lock();//里面有数据了,为了下面finally中读锁.我再加上读锁.
			}
		}finally{
			rwl.readLock().unlock();
		}
		return value;
	}
}

 

 

 

 

 

 

上面代码,是所属于Hibernate的.下面有相关介绍:

Hibernate

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。

面试题:设计一个缓存系统,中设计到.Api中的一个例子:

 

 

 

条件阻塞Condition的应用

 

 

package cn.itcast.extend.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//java5条件阻塞Condition的应用

//一道面试题:子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,如此循环50次.交替进行.
public class ConditionCommunication {
		public static void main(String[] args) {
			final Business business=new ConditionCommunication().new Business();
			System.out.println("Hello");
			//new一个线程(子线程)
			new Thread(
			new Runnable(){
				@Override
				public void run() {
						for(int i=1;i<=50;i++){
							business.sub(i);
						}
				}
			}
			).start();
		
			//main主线程
			for(int i=1;i<=50;i++){
				business.main(i);
			}
		}

/*经验:要用到共同数据(包括同步锁)或共同算法的若干个方法应该归在同一个类身上,这种设计正好体现了高类聚
和程序的健壮性*/
class  Business{
	Lock lock=new ReentrantLock();
	Condition conditionSub=lock.newCondition();
	Condition conditionMain=lock.newCondition();
	private int flag=2;
	
	
	//一定要注意,用lock了,就别用Synchronized,这样会死锁的...................................
	//子线程
	public  void sub(int i){//如果去掉synchronized,就会报错.
		lock.lock();
		try{
			while(flag!=2){
			conditionSub.await();
			}
		for(int j=1;j<=10;j++){
			System.out.println("sub thread sequence of:"+j+",loop of:"+i);
		}
		flag=1;
		conditionMain.signal();
		}catch(Exception e){
			e.printStackTrace();
		}
		finally{
			lock.unlock();
		}
		
	}
	
	
	//主线程
	public  void main(int i){
		lock.lock();
		try{
			while(flag!=1){
				conditionMain.await();
			}
		for(int j=1;j<=100;j++){
			System.out.println("main thread sequence of:"+j+",loop of:"+i);
		}
		flag=2;
		conditionSub.signal();
		}catch(Exception e){
			System.out.println(e);
		}
		finally{
		lock.unlock();
	}
	}
}
}

 

 

 

 

 

其中,涉及到-----阻塞的队列底层实现

Api提供的实例:

 

Semaphere同步工具

 

Lock锁,和Semaphore实现互斥锁的区别:

Lock只能被,加锁的对象锁释放.而Semaphore被锁上后,还可以被别人释放.

 

下面,是在构造函数中,修改fair,为true来改变先来后到的顺序....

 

 

 

package cn.itcast.extend.thread;


/*semaphore
				|---acquire();获取
				|---release();释放
				|--availablePermits;有效的许可
*/

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {
		public static void main(String[] args) {
		ExecutorService service=Executors.newCachedThreadPool();
		final Semaphore sp=new Semaphore(3);
		
		
		for(int i=0;i<10;i++){
			Runnable runnable=new Runnable() {
				@Override
				public void run() {
				try{
					sp.acquire();//acquire[获取]
				}catch(InterruptedException e1){
					e1.printStackTrace();
				}
				System.out.println("线程"+Thread.currentThread().getName()+"进入,当前已有"+
				(3-sp.availablePermits())+"个并发");
				try{
					Thread.sleep((long)(Math.random()*10000));
				}catch(InterruptedException e){
					e.printStackTrace();
				}
				System.out.println("线程"+Thread.currentThread().getName()+"即将离开");
				sp.release();//release[释放]
				System.out.println("线程"+Thread.currentThread().getName()+"已离开,当前已有"
				+(3-sp.availablePermits())+"个并发");
				}
			};
		service.execute(runnable);
			
		}
		
		
		
			
			
			
			
		}
}

 

 

 

 

 

 

CyclicBarrier同步工具

 

 

package cn.itcast.extend.thread;
//java5的CyclicBarrier同步工具

/*CyclicBarrier
 				|-----await();
 				|-----getNumberWaiting();返回当前在屏障处等待的参与者数目。此方法主要用于调试和断言。 
	 */
//

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class CyclicBarrierTest {
	public static void main(String[] args) {
		//来一个动态的线程池
		ExecutorService service = Executors.newCachedThreadPool();
		//建一个障碍.....主角上场...
		final CyclicBarrier cb=new CyclicBarrier(3);

		
		//循环三次,往线程池中丢三次....
		for (int i = 1; i <= 3; i++) {
			Runnable runnable = new Runnable() {
				@Override
				public void run() {
					try {
						//随机生成时间,来代表每个小伙伴们到达的时间
						Thread.sleep((long) (Math.random() * 10000));//千万记着括号......罪过..		
						System.out.println("线程"
								+ Thread.currentThread().getName()
								+ "即将到达集合地点1,当前已有"
								+ (cb.getNumberWaiting()+1)//  返回当前在屏障处等待的参与者数目。
								+ "个已经到达,"
								+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊"
										: "正在等候"));
						cb.await();

						Thread.sleep((long) (Math.random() * 10000));
						System.out.println("线程"
								+ Thread.currentThread().getName()
								+ "即将到达集合地点2,当前已有"
								+ (cb.getNumberWaiting() + 1)//这里加1,是因为,这个线程还没走到下面那个await().
								+ "个已经到达,"							//此时,返回是0,所以,这里是预先打印出来的.
								+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊"//这里判断==2,是这个情况.
										: "正在等候"));

						cb.await();

						Thread.sleep((long) (Math.random() * 10000));
						System.out.println("线程"
								+ Thread.currentThread().getName()
								+ "即将到达集合地点3,当前已有"
								+ (cb.getNumberWaiting() + 1)
								+ "个已经到达"
								+ (cb.getNumberWaiting() == 2 ? ",都到齐了,不用走了,休息下吃点饭把."
										: "正在等候"));

						cb.await();
						
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			};
			service.execute(runnable);//每建一个Runnble后,将其丢尽线程池中...
		}
			service.shutdown();//最后,所有的线程都闲了,,就关掉池子把...
	}
}


 

 

package cn.itcast.extend.thread;
//java5的CountDownLatch同步工具		CountDown[倒计时]	   Latch[锁存器]  
//可以模拟:运动场上,裁判一声"枪"下,运动员们听到枪声后,开始跑百米,当这几个运动员全部,跑完后,裁判员再公布名次.

	/*CountDownLatch	
 						|------await(); 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。
 						|------countDown();  递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
	*/ 
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class CountDownLatchTest {
	public static void main(String[] args){
		//老样子,来一个,线程池
		ExecutorService service=Executors.newCachedThreadPool();
		 
		//两个(计数器)
		final CountDownLatch cdOrder=new CountDownLatch(1);//Order[命令]
		final CountDownLatch cdAnswer=new CountDownLatch(3);//Answer[回答,回应]
		
		//循环三次.创造线程.
		for(int i=1;i<=3;i++){
			Runnable runnable=new Runnable() {
				@Override
				public void run() {
					try {
						System.out.println("线程"+Thread.currentThread().getName()+"正准备接受命令");
						
						cdOrder.await();//当计数器中,的数字变成1的时候,就可以,继续往下走.
						
						System.out.println("线程"+Thread.currentThread().getName()+"已经接受命令");
						Thread.sleep((long)(Math.random()*10000));//这个任务需要一定的时间哈...[比如跑百米]
				
						System.out.println("线程"+Thread.currentThread().getName()+"回应命令处理结果");
						cdAnswer.countDown();//  递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
						
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			};
			service.execute(runnable);//丢尽线程池
		}
		try{
			Thread.sleep((long)(Math.random()*10000));
			System.out.println("线程"+Thread.currentThread().getName()+"即将发布命令");
			cdOrder.countDown();
			System.out.println("线程"+Thread.currentThread().getName()+"已发送命令,正在等待结果");
			cdAnswer.await();
			System.out.println("线程"+Thread.currentThread().getName()+"已收到所有响应结果");
		}catch(Exception e){
			e.printStackTrace();
		}
		service.shutdown();
	}
}

 

 

 

 

 

 

package cn.itcast.extend.thread;
//java5的Exchanger同步工具
//可以模拟,双方共到一个目的地交换彼此的物件.
//两个线程碰到一起后,互相交换数据
	/*Exchanger<V>
 					|-----exchange(V x)等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。
	 */



import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExchangerTest {
	public static void main(String[] args) {
		ExecutorService servise=Executors.newCachedThreadPool();//一个动态的线程池
		
		final Exchanger<String> exchanger=new Exchanger<String>();
		
		//往线程池中丢一个线程.
		servise.execute(new Runnable() {
			@Override
			public void run() {
			try{
				String data="物";
				System.out.println("线程"+Thread.currentThread().getName()+"到达目的地");
				System.out.println("线程"+Thread.currentThread().getName()+"正在把数据["+data+"]换出去");
				Thread.sleep((long)(Math.random()*10000));
				data=exchanger.exchange(data);
				System.out.println("线程"+Thread.currentThread().getName()+"换回的数据为["+data+"]");
			}catch(Exception e){
				e.printStackTrace();
			}
			}
		});
		
		//往线程池中再丢一个线程.
		servise.execute(new Runnable() {
			@Override
			public void run() {
			try{
				String data="钱";
				System.out.println("线程"+Thread.currentThread().getName()+"到达目的地");
				
				System.out.println("线程"+Thread.currentThread().getName()+"正在把数据["+data+"]换出去");
				Thread.sleep((long)(Math.random()*10000));
				data=exchanger.exchange(data);
				
				System.out.println("线程"+Thread.currentThread().getName()+"换回的数据为["+data+"]");
			}catch(Exception e){
				e.printStackTrace();
			}
			}
		});
		
		servise.shutdown();
	}
}

 

 

 

 

 

 

 

 

java5阻塞队列的应用

 

 

 

同步集合类的应用

 

讲之前,先看看并发库中已经学过的知识们:

都在java.util.concurrent包中---------

    其中老师谈到,在队列中,有两个实现类,1,linked链表[可以不固定大小]   2,Array[必须固定大小]

底层机制:连续的一片内存[数组]   不连续的一片内存[链表]

 

在没有1.5并发库之前,实现多线程访问集合,可以用Collections中的SynchronizedMap();

 

 

 

在迭代器中不能对集合中的数据进行操作----------原理.

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值