第九讲
线程池
写tomcat类似的程序非常难,效率上不去。
来一个连接,就会启动一个线程,和客户端对话
比如婚礼接待,来一个客人找一个人帮忙招待
new Thread(){
run(){
while(查询某个池子中是否还有客户要接待){
接待与聊一会
}
}
}.start();
当接待一个客户就扔到池子里面,然后线程从池子里面取(这时候需要通知notifyAll休眠的线程)
public class ThreadPoolTest{
public static void main(String[] args){
ExcutorServices threadPool = Executors.newFixedThreadPool(3);
for(int i = 1; i <=10; i++){
final int task = i;
threadPool.execute(new Runnable(){
@Override
public void run(){
for (int j= 1; j < 10; j++){
Thread.sleep(20);
System.out.println(Thread.currentThread().getName + “ is looping of ” + i + “task of ” + task);
}
}
})
}
System.out.println(“all of 10 tasks have committed”);
//没事干了,所有事情都做完了。才销毁
threadPool.shutDown();
}
}
还有一种缓存的线程池
还有一种就是只有一个线程的池(如何实现线程死掉之后重新启动)
还有一种启动定时器
第十讲
Callable&Future
Callabel可以获取线程执行完的返回结果
public class CallabelAndFuture{
public static void main(String[] args){
ExecutorService threadPool = Executors.newSingleThreadExecuter();
Future<String> future =
threadPool.submit(
new Callable<String>(){
public String call() throws Exception{
Thread.sleep(2000);
return “hello”;
}
}
);
System.out.println(“等待结果”);
System.out.println(“拿到结果” + future.get());
}
}
//Future取得的结果类型和Callable返回的结果类型必须一致,这是通过泛型来实现的
//Callable要采用ExecutorService的submet方法提交,返回的future对象可以取消任务
//CompletionService用于提交一组Callable任务,其take方法返回已完成的一个Callabel任务对应的Future对象
例如:好比同时种了几块地的麦子,然后就等待收割。收割时,则是那块先成熟了,就先去收割那块麦子
ExecutorService threadPool = Executors.newFixedThreadPool(10);
CompletionService< Integer > completionService = new ExecutorCompletionService<Integer>( threadPool);
for (int i = 0; i < 10 ; i++){
final int seq = i;
completionService.submit(new Callable<Integer>(){
@Override
public Integer call() throws Exception{
Thread.sleep(new Random().nextInt(5000));
return seq;
}
})
}
for (int i = 0; i < 10; i++){
System.out.println(System.out.println(completionService.take().get()));
}
第十一讲
Lock&Condition实现线程同步通信
Lock相当于传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象,两个线程执行的代码片段要实现同步互斥的效果,他们必须用同一个Lock对象。锁是上在代表要保护的资源的类的同步方法中
class Computer{
Lock lock = new ReentrantLock();
public void output(String name){
int len = name.length();
lock.lock();
try{
for (int k = 0; k < len; k++){
System.out.println(name.charAt(i));
}
}
finally{
lock.unlock();
}
}
}
第十二讲
读写锁
读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,这是jvm自己控制的,你只要上好相应的锁即可。如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁,总之,读的时候上读锁,写的时候上写锁。
三个线程读数据,三个线程写数据(写一个应用代码),能够提高性能,又能提高互斥
ReadWriteLock rw1 = new ReentrantReadWriteLock();
读方法内的代码
rw1.readLock().lock()
try{
}
finally{
rw1.readLock().unLock();
}
rw1.writeLock().lock()
rw1.writeLock().unLock();
Hibernate 的session.load(id, User.class);和session.get(id, User.class)的区别
load查缓存数据,查不到就去数据库中找,找不到抛异常
get直接去数据库中取,找不到就返回null
还有一种读写锁。(既可以读,也可以锁)
第十三讲
Condition的功能类似在传统线程技术中的object.wait和object.notify的功能。
Condition是基于锁之上的
编程语言就是一个工具,最重要的是思想。不要在意学什么语言好
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
condition.await();
condition.signal();
条件放到while()里面防止虚假唤醒
阻塞队列(起到缓冲的效果)
用到两个condition,用一个也能解决问题,只用一个Condition会出现问题,
两个Condition,放的时候唤醒取的线程,不要唤醒放的线程
Condition可以实现多路Condition
转载请注明:学时网 » 张孝祥老师-java并发编程听课笔记(四)