广州网站建设平台网站运营策划书
1、锁的7大分类
2.Lock接口的常见方法有哪些?
解释:
1.lock() - 加锁
2.lockInterruptibly() - 实现可中断的锁
3.tryLock() - 尝试获取锁,只会尝试一次
4.unlock() - 解锁
5.newCondition() -
方法示例:
void lock() -
package imooc4.lock;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @Description: 测试lock接口*/
public class TestLock {static int count = 0;public static void main(String[] args) throws InterruptedException {Lock lock = new ReentrantLock();//模拟多个线程执行++操作 结果1000List<Thread> list = new ArrayList<>();for (int i = 0; i < 10; i++) {Thread thread = new Thread(() -> {for (int j = 0; j < 100; j++) {lock.lock();try {count++;} finally {lock.unlock();}}});list.add(thread);}for (Thread thread : list) {thread.start();}for (Thread thread : list) {thread.join();}System.out.println(count);//如果是1000结果就是正确的}
}
运行结果:boolean tryLock() -
package imooc4.lock;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @Description:* Lock lock = ...;* * if (lock.tryLock()) {* * try {* * // manipulate protected state* * } finally {* * lock.unlock();* * }* * } else {* * // perform alternative actions* * }}</pre>*/
public class TestTryLock {public static void main(String[] args) {Lock lock = new ReentrantLock();for (int i = 0; i < 10; i++) {new Thread(()->{if(lock.tryLock()){try {System.out.println("拿到了锁");Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.unlock();}}else{System.out.println("没拿到锁");}}).start();}}
}
运行结果:boolean tryLock(long time, TimeUnit unit) -
package imooc4.lock;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @Description:*/
public class TestTryLockWithTimeOut {public static void main(String[] args) {Lock lock = new ReentrantLock();Thread thread = new Thread(() -> {try {if (lock.tryLock(1, TimeUnit.SECONDS)) {System.out.println(Thread.currentThread().getName() + " 拿到了锁");} else {System.out.println(Thread.currentThread().getName() + " 没拿到锁");return;}} catch (InterruptedException e) {throw new RuntimeException(e);}try {//临界资源的操作System.out.println(Thread.currentThread().getName() + " 正在操作临界资源");Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.unlock();}});Thread thread1 = new Thread(() -> {try {if (lock.tryLock(1, TimeUnit.SECONDS)) {System.out.println(Thread.currentThread().getName() + " 拿到了锁");} else {System.out.println(Thread.currentThread().getName() + " 没拿到锁");return;}} catch (InterruptedException e) {throw new RuntimeException(e);}try {//临界资源的操作System.out.println(Thread.currentThread().getName() + " 正在操作临界资源");Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.unlock();}});thread.start();thread1.start();}
}
运行结果:
3.Lock锁如何实现生产者消费者模式-Condition接口?
之前实现的场景
之前是通过锁对象的wait()和notifyAll()实现的吃自助餐的场景
现在通过Lock和Condition实现
、如果只有一个Condtion,那它的和Synchronized的实现机制是一样的,如果创建多个Condtion,会让等待唤醒机制更加灵活。
package imooc4.condition;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @Description:*/
public class Desk {//标注桌子上是否有食物public static boolean flag = false;public static final Lock lock = new ReentrantLock();//给consumer用的conditionpublic static Condition condition4Consumer = lock.newCondition();//给producer用的conditionpublic static Condition condition4Producer = lock.newCondition();
}
package imooc4.condition;/*** @Description:*/
public class Consumer extends Thread{@Overridepublic void run() {while (true){//不断地拿食物Desk.lock.lock();try {if(Desk.flag){//如果有实物 拿走,并通知厨师System.out.println("顾客取走食物");Desk.flag = false;System.out.println("consumer 准备唤醒producer");Desk.condition4Producer.signalAll();}else{try {Desk.condition4Consumer.await();} catch (InterruptedException e) {throw new RuntimeException(e);}}}finally {Desk.lock.unlock();}}}
}
package imooc4.condition;/*** @Description:*/
public class Producer extends Thread{@Overridepublic void run() {while (true){Desk.lock.lock();try {if(Desk.flag){//厨师等待try {Desk.condition4Producer.await();} catch (InterruptedException e) {throw new RuntimeException(e);}}else{//厨师开始工作System.out.println("厨师正在补充食物");Desk.flag = true;System.out.println("producer 准备唤醒consumer");Desk.condition4Consumer.signalAll();}}finally {Desk.lock.unlock();}}}
}
package imooc4.condition;/*** @Description:*/
public class TestConsumerAndProducer {public static void main(String[] args) {Producer producer = new Producer();Producer producer1 = new Producer();Producer producer2 = new Producer();Producer producer3= new Producer();Consumer consumer = new Consumer();Consumer consumer1 = new Consumer();Consumer consumer2 = new Consumer();Consumer consumer3 = new Consumer();producer.start();producer1.start();producer2.start();producer3.start();consumer.start();consumer1.start();consumer2.start();consumer3.start();}
}
运行结果:
4.选用锁时该用synchronized关键是还是Lock接口?
5.公平锁与非公平锁应该选用哪个?
公平锁 -
package imooc4.fair;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @Description: 测试公平锁*/
public class TestFairLock {//公平锁static Lock lock = new ReentrantLock(true);public static void main(String[] args) {//创建多个线程,每个线程多次加锁,// 拿到锁后检查时哪个线程拿到的锁for (int i = 0; i < 3; i++) {new Thread(()->{for (int j = 0; j < 2; j++) {//加锁lock.lock();try {System.out.println("当前获取锁的线程"+Thread.currentThread().getName());}finally {lock.unlock();}}}).start();}}
}
运行结果:
非公平锁 -
package imooc4.fair;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @Description:*/
public class TestUnfairLock {//非公平锁static Lock lock = new ReentrantLock(false);public static void main(String[] args) {//创建多个线程,每个线程多次加锁,// 拿到锁后检查时哪个线程拿到的锁for (int i = 0; i < 3; i++) {new Thread(()->{for (int j = 0; j < 2; j++) {//加锁lock.lock();try {System.out.println("当前获取锁的线程"+Thread.currentThread().getName());}finally {lock.unlock();}}}).start();}//A B C//A-1 A-2//B-1 B-2//C-1 C-2}
}
运行结果:
6.(可中断和不可中断)如何使用Lock接口实现可中断锁?
代码示例:
package imooc4.interrupt;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @Description: 测试可中断锁*/
public class TestInterruptLock {static final Lock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {//受害人转账线程 尝试获取可中断锁Thread thread = new Thread(() -> {try {lock.lockInterruptibly();} catch (InterruptedException e) {System.out.println("受害人转账操作取消,钱财找回,谢谢民警");return;}try {System.out.println("受害 人开始转账给骗子");} finally {lock.unlock();}});Thread thread1 = new Thread(() -> {try {lock.lockInterruptibly();} catch (InterruptedException e) {}try {Thread.sleep(3000);System.out.println("其他的转账线程");} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.unlock();}});//其他转账线程执行thread1.start();Thread.sleep(100);//受害人转账线程执行thread.start();Thread.sleep(100);thread.interrupt();}
}
运行结果:
7.(共享锁独占锁)如何根据读操作和写操作拆分锁粒度-读写锁ReadWriteLock?
所以readLock、writeLock返回的是Lock的实现类。
package imooc4.lock;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;/*** @Description:测试读读不互斥,读写互斥*/
public class TestReentrantReadWriteLock {final static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();final static Lock writeLock = readWriteLock.writeLock();final static Lock readLock = readWriteLock.readLock();// final static Lock lock = new ReentrantLock();public static void main(String[] args) {Thread thread = new Thread(() -> {writeLock.lock();try {Thread.sleep(1000);System.out.println(System.currentTimeMillis());} catch (InterruptedException e) {throw new RuntimeException(e);} finally {writeLock.unlock();}});Thread thread1 = new Thread(() -> {writeLock.lock();try {Thread.sleep(1000);System.out.println("要进行写操作,需要与其他读操作互斥,也需要与其他写操作互斥");System.out.println(System.currentTimeMillis());} catch (InterruptedException e) {throw new RuntimeException(e);} finally {writeLock.unlock();}});thread.start();thread1.start();}
}
模拟电商场景:
package imooc4.lock.demo;import java.util.concurrent.locks.ReentrantReadWriteLock;/*** @Description:*/
public class Product {//商品名称private String name;//价格private double price;//赠送private double coupon;private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();public String getName() {return name;}public double getPrice() {lock.readLock().lock();try {return price;}finally {lock.readLock().unlock();}}public double getCoupon() {lock.readLock().lock();try {return coupon;}finally {lock.readLock().unlock();}}public void updateProductInfo(double newPrice,double newCoupon){lock.writeLock().lock();try {this.price = newPrice;Thread.sleep(1000);this.coupon = newCoupon;} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.writeLock().unlock();}}public Product(String name, double price, double coupon) {this.name = name;this.price = price;this.coupon = coupon;}@Overridepublic String toString() {return "Product{" +"name='" + name + '\'' +", price=" + price +", Coupon=" + coupon +", lock=" + lock +'}';}
}
package imooc4.lock.demo;/*** @Description:*/
public class TestProduct {public static void main(String[] args) throws InterruptedException {Product product = new Product("拉杆箱",200,150);System.out.println(product);Thread writeThread = new Thread(()->{product.updateProductInfo(150,100);});Thread readThread = new Thread(() -> {double price = product.getPrice();double coupon = product.getCoupon();System.out.println(price);System.out.println(coupon);});writeThread.start();Thread.sleep(500);readThread.start();
// System.out.println(product);}
}
运行结果:
8.(读写锁)读写锁ReadWriteLock何时使用锁的降级?
大白话:
释放写锁,再获取读锁,与不释放写锁,先获取读锁,再释放写锁的区别?
释放写锁,再获取读锁 - 就是普通锁的获取与释放的过程,中间会产生时间间隔,锁可能被其他的写线程抢占;
不释放写锁,先获取读锁,再释放写锁 - 这把锁就不会被别的写线程抢占,锁的降级。
注意:
如果先读锁,再获取写锁 - 这里不是升级锁,而是先读锁解锁,再获取写锁。
代码案例:
package imooc4.lock.demo;import java.util.concurrent.locks.ReentrantReadWriteLock;/*** @Description:*/
public class Product {//商品名称private String name;//价格private double price;//赠送private double coupon;private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();public String getName() {return name;}public double getPrice() {lock.readLock().lock();try {return price;}finally {lock.readLock().unlock();}}public double getCoupon() {lock.readLock().lock();try {return coupon;}finally {lock.readLock().unlock();}}public void updateProductInfo(double newPrice,double newCoupon){lock.writeLock().lock();try {this.price = newPrice;Thread.sleep(1000);this.coupon = newCoupon;} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.writeLock().unlock();}}public Product(String name, double price, double coupon) {this.name = name;this.price = price;this.coupon = coupon;}@Overridepublic String toString() {return "Product{" +"name='" + name + '\'' +", price=" + price +", Coupon=" + coupon +", lock=" + lock +'}';}
}
package imooc4.lock.demo;import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Supplier;/*** @Author: Alfred* @ModuleOwner: Alfred* @Description:**** class CachedData {* Object data;* boolean cacheValid;* final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();** void processCachedData() {* rwl.readLock().lock();* if (!cacheValid) {* // Must release read lock before acquiring write lock* rwl.readLock().unlock();* rwl.writeLock().lock();* try {* // Recheck state because another thread might have* // acquired write lock and changed state before we did.* if (!cacheValid) {* data = ...;* cacheValid = true;* }* // Downgrade by acquiring read lock before releasing write lock* rwl.readLock().lock();* } finally {* rwl.writeLock().unlock(); // Unlock write, still hold read* }* }** try {* use(data);* } finally {* rwl.readLock().unlock();* }* }* }}*/
public class CachedData<T> {T data;boolean cacheValid;final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();public void setCacheValid(boolean cacheValid) {this.cacheValid = cacheValid;}/*** 查询缓存或者设置缓存* 如果缓存有效,则使用缓存*/public T processCachedData(Supplier<T> supplier){readWriteLock.readLock().lock();//如果缓存有效就读//如果缓存失效,则写if(!cacheValid){//必须先解锁在加锁readWriteLock.readLock().unlock();readWriteLock.writeLock().lock();//更新缓存try {if(!cacheValid){data = supplier.get();cacheValid = true;}//锁降级开始//没有释放锁,这个锁会和其他写线程阻塞,为了保护 ---System.out.println(data);readWriteLock.readLock().lock();}finally {readWriteLock.writeLock().unlock();}}try {//使用缓存return data;}finally {readWriteLock.readLock().unlock();}}
}
package imooc4.lock.demo;import org.junit.Test;import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;/*** @Description: 商品上架,更新,下架业务*/
public class ProductService {//商品信息缓存 productName -> CachedDataMap<String,CachedData<Product>> map = new ConcurrentHashMap<>();Map<String,Product> mockDataBase = new HashMap<>();@Testpublic void TestCache(){CachedData<Product> cachedData = new CachedData<Product>();String productName = "trunk";Product product = cachedData.processCachedData(() -> new Product(productName, 200, 150));map.put(productName,cachedData);product.updateProductInfo(150,100);cachedData.setCacheValid(false);//从db查询数据Product product1 = cachedData.processCachedData(this::queryDataFromDb);System.out.println(product1);}@Testpublic void testProduct() throws InterruptedException {new Thread(this::saveProduct).start();Thread.sleep(50);final String productName = "trunk";//下单线程1new Thread(()->{Product product = queryProduct(productName);if(Objects.nonNull(product)){System.out.println("用户拿着这个"+product.getName()+"下单了,价格:"+product.getPrice()+"赠送优惠券"+product.getCoupon());}}).start();Thread.sleep(50);//更新商品new Thread(()->updateProduct(productName)).start();Thread.sleep(50);//模拟并发写缓存//多个线程同时下单//下单线程2new Thread(()->{Product product = queryProduct(productName);if(Objects.nonNull(product)){System.out.println("用户拿着这个"+product.getName()+"下单了,价格:"+product.getPrice()+"赠送优惠券"+product.getCoupon());}}).start();//下单线程3new Thread(()->{Product product = queryProduct(productName);if(Objects.nonNull(product)){System.out.println("用户拿着这个"+product.getName()+"下单了,价格:"+product.getPrice()+"赠送优惠券"+product.getCoupon());}}).start();while (true){}}/*** 商品上架 (保存商品)* @return*/public int saveProduct(){String productName = "trunk";Product product = new Product(productName,200,150);//保存数据到数据库mockDataBase.put(productName,product);return 1;}/*** 查询商品信息* @param productName* @return*/public Product queryProduct(String productName){CachedData<Product> cacheData = getCacheData(productName);return cacheData.processCachedData(()->mockDataBase.get(productName));}private CachedData<Product> getCacheData(String productName) {
// //操作1
// CachedData<Product> cachedData = map.get(productName);
// if(cachedData==null){
// map.put(productName,new CachedData<>());
// }//操作2return map.compute(productName, (k, v) -> {if (v == null) {return new CachedData<>();} else {return v;}});}/*** 更新商品* @param productName* @return*/public int updateProduct(String productName){Product product = queryProduct(productName);if(Objects.isNull(product)){return 0;}product.updateProductInfo(150,100);mockDataBase.put(productName,product);CachedData<Product> cacheData = getCacheData(productName);cacheData.setCacheValid(false);map.put(productName,cacheData);return 1;}/*** 商品下架* @return*/public int deleteProduct(String productName){//查询商品Product product = queryProduct(productName);if(Objects.isNull(product)){return 0;}mockDataBase.remove(productName);map.remove(productName);return 1;}private Product queryDataFromDb() {return new Product("trunk",150,100);}
}
、
package imooc4.lock.demo;import java.util.concurrent.locks.ReentrantReadWriteLock;/*** @Description:*/
public class Product {//商品名称private String name;//价格private double price;//赠送private double coupon;private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();public String getName() {return name;}public double getPrice() {lock.readLock().lock();try {return price;}finally {lock.readLock().unlock();}}public double getCoupon() {lock.readLock().lock();try {return coupon;}finally {lock.readLock().unlock();}}public void updateProductInfo(double newPrice,double newCoupon){lock.writeLock().lock();try {this.price = newPrice;Thread.sleep(1000);this.coupon = newCoupon;} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.writeLock().unlock();}}public Product(String name, double price, double coupon) {this.name = name;this.price = price;this.coupon = coupon;}@Overridepublic String toString() {return "Product{" +"name='" + name + '\'' +", price=" + price +", Coupon=" + coupon +", lock=" + lock +'}';}
}
package imooc4.lock.demo;import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Supplier;/*** @Author: Alfred* @ModuleOwner: Alfred* @Description:**** class CachedData {* Object data;* boolean cacheValid;* final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();** void processCachedData() {* rwl.readLock().lock();* if (!cacheValid) {* // Must release read lock before acquiring write lock* rwl.readLock().unlock();* rwl.writeLock().lock();* try {* // Recheck state because another thread might have* // acquired write lock and changed state before we did.* if (!cacheValid) {* data = ...;* cacheValid = true;* }* // Downgrade by acquiring read lock before releasing write lock* rwl.readLock().lock();* } finally {* rwl.writeLock().unlock(); // Unlock write, still hold read* }* }** try {* use(data);* } finally {* rwl.readLock().unlock();* }* }* }}*/
public class CachedData<T> {T data;boolean cacheValid;final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();public void setCacheValid(boolean cacheValid) {this.cacheValid = cacheValid;}/*** 查询缓存或者设置缓存* 如果缓存有效,则使用缓存*/public T processCachedData(Supplier<T> supplier){readWriteLock.readLock().lock();//如果缓存有效就读//如果缓存失效,则写if(!cacheValid){//必须先解锁在加锁readWriteLock.readLock().unlock();readWriteLock.writeLock().lock();//更新缓存try {if(!cacheValid){data = supplier.get();cacheValid = true;}//锁降级开始//没有释放锁,这个锁会和其他写线程阻塞,为了保护 ---System.out.println(data);readWriteLock.readLock().lock();}finally {readWriteLock.writeLock().unlock();}}try {//使用缓存return data;}finally {readWriteLock.readLock().unlock();}}
}
package imooc4.lock.demo;import org.junit.Test;import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;/*** @Description: 商品上架,更新,下架业务*/
public class ProductService {//商品信息缓存 productName -> CachedDataMap<String,CachedData<Product>> map = new ConcurrentHashMap<>();Map<String,Product> mockDataBase = new HashMap<>();@Testpublic void TestCache(){CachedData<Product> cachedData = new CachedData<Product>();String productName = "trunk";Product product = cachedData.processCachedData(() -> new Product(productName, 200, 150));map.put(productName,cachedData);product.updateProductInfo(150,100);cachedData.setCacheValid(false);//从db查询数据Product product1 = cachedData.processCachedData(this::queryDataFromDb);System.out.println(product1);}@Testpublic void testProduct() throws InterruptedException {new Thread(this::saveProduct).start();Thread.sleep(50);final String productName = "trunk";//下单线程1new Thread(()->{Product product = queryProduct(productName);if(Objects.nonNull(product)){System.out.println("用户拿着这个"+product.getName()+"下单了,价格:"+product.getPrice()+"赠送优惠券"+product.getCoupon());}}).start();Thread.sleep(50);//更新商品new Thread(()->updateProduct(productName)).start();Thread.sleep(50);//模拟并发写缓存//多个线程同时下单//下单线程2new Thread(()->{Product product = queryProduct(productName);if(Objects.nonNull(product)){System.out.println("用户拿着这个"+product.getName()+"下单了,价格:"+product.getPrice()+"赠送优惠券"+product.getCoupon());}}).start();//下单线程3new Thread(()->{Product product = queryProduct(productName);if(Objects.nonNull(product)){System.out.println("用户拿着这个"+product.getName()+"下单了,价格:"+product.getPrice()+"赠送优惠券"+product.getCoupon());}}).start();while (true){}}/*** 商品上架 (保存商品)* @return*/public int saveProduct(){String productName = "trunk";Product product = new Product(productName,200,150);//保存数据到数据库mockDataBase.put(productName,product);return 1;}/*** 查询商品信息* @param productName* @return*/public Product queryProduct(String productName){CachedData<Product> cacheData = getCacheData(productName);return cacheData.processCachedData(()->mockDataBase.get(productName));}private CachedData<Product> getCacheData(String productName) {
// //操作1
// CachedData<Product> cachedData = map.get(productName);
// if(cachedData==null){
// map.put(productName,new CachedData<>());
// }//操作2return map.compute(productName, (k, v) -> {if (v == null) {return new CachedData<>();} else {return v;}});}/*** 更新商品* @param productName* @return*/public int updateProduct(String productName){Product product = queryProduct(productName);if(Objects.isNull(product)){return 0;}product.updateProductInfo(150,100);mockDataBase.put(productName,product);CachedData<Product> cacheData = getCacheData(productName);cacheData.setCacheValid(false);map.put(productName,cacheData);return 1;}/*** 商品下架* @return*/public int deleteProduct(String productName){//查询商品Product product = queryProduct(productName);if(Objects.isNull(product)){return 0;}mockDataBase.remove(productName);map.remove(productName);return 1;}private Product queryDataFromDb() {return new Product("trunk",150,100);}
}
package imooc4.lock.demo;/*** @Description:*/
public class TestProduct {public static void main(String[] args) throws InterruptedException {Product product = new Product("拉杆箱",200,150);System.out.println(product);Thread writeThread = new Thread(()->{product.updateProductInfo(150,100);});Thread readThread = new Thread(() -> {double price = product.getPrice();double coupon = product.getCoupon();System.out.println(price);System.out.println(coupon);});writeThread.start();Thread.sleep(500);readThread.start();
// System.out.println(product);}
}
9.(共享锁)信号量Semaphore的应用场景
参考:Java并发神器Semaphore全方位解析_java semaphore-CSDN博客
实现限流器逻辑:
package imooc4.semaphore;import java.util.concurrent.Semaphore;
import java.util.function.Supplier;/*** @Description:使用semaphore实现限流功能*/
public class LimitedTask<T> implements Runnable{private String name;private Semaphore semaphore;private Supplier<T> supplier;public LimitedTask(String name, Semaphore semaphore,Supplier<T> supplier) {this.name = name;this.semaphore = semaphore;this.supplier = supplier;}@Overridepublic void run() {try {//请求许可,如果许可不足,会被阻塞直到有可用的许可semaphore.acquire();System.out.println(name+" 正在执行");supplier.get();System.out.println(name+" 执行结束");} catch (InterruptedException e) {throw new RuntimeException(e);}finally {semaphore.release();}}
}
package imooc4.semaphore;import java.util.concurrent.Semaphore;/*** @Description:*/
public class TestLimitedTask {public static void main(String[] args) {int maxTaskCount = 2;Semaphore semaphore = new Semaphore(maxTaskCount);//启动多个线程,交给LimitedTask去执行for (int i = 0; i <= 5; i++) {String taskName = "Task "+i;Thread thread = new Thread(new LimitedTask(taskName, semaphore,()->{//下单的逻辑try {Thread.sleep(5000);} catch (InterruptedException e) {throw new RuntimeException(e);}return taskName;}));thread.start();}}
}
运行结果:
实现资源池逻辑:
package imooc4.semaphore;import java.util.concurrent.Semaphore;/*** @Description:*/
public class ObjectPool<T> {//资源池大小private final int poolSize;//semaphore大小跟资源池大小一样private final Semaphore semaphore;//对象都有哪些private final T[] objects;//对象是否使用private final boolean[] isUsed;public ObjectPool( T[] objects) {this.poolSize = objects.length;this.semaphore = new Semaphore(poolSize);this.objects = objects;this.isUsed = new boolean[poolSize];}//获取许可public T acquire() throws InterruptedException {//拿到许可后获取对象池中的对象semaphore.acquire();return getObject();}//释放许可public void release(T obj){if(returnObject(obj)){semaphore.release();}}private synchronized boolean returnObject(T obj) {for (int i = 0; i < poolSize; i++) {if(objects[i]==obj&&isUsed[i]){isUsed[i] = false;return true;}}return false;}private synchronized T getObject() {for (int i = 0; i < poolSize; i++) {if(!isUsed[i]){isUsed[i] = true;return objects[i];}}return null;}
}
package imooc4.semaphore;/*** @Description:测试对象池*/
public class TestObjectPool {public static void main(String[] args) {Integer[] poolObjects = new Integer[]{1,2,3,4,5};ObjectPool<Integer> objectPool = new ObjectPool<>(poolObjects);//创建多个线程获取对象池中的对象for (int i = 0; i < 7; i++) {new Thread(()->{try {Integer obj = objectPool.acquire();if(obj!=null){System.out.println(Thread.currentThread().getName()+" 获取到了: "+ obj);Thread.sleep(3000);objectPool.release(obj);}else{System.out.println(Thread.currentThread().getName()+"对象池耗尽");}} catch (InterruptedException e) {throw new RuntimeException(e);}}).start();}}
}
运行结果:
10.(死锁):什么是死锁?如何排查死锁问题?
演示代码:
package imooc4.lock.deadlock;/*** @Description:*/
public class TestDeadLock {public static void main(String[] args) {Object lock = new Object();Object lock1 = new Object();new Thread(()->{synchronized (lock){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (lock1){System.out.println("拿到锁");}}}).start();new Thread(()->{synchronized (lock1){try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (lock){System.out.println("拿到锁");}}}).start();}
}
运行结果:
结论:
两个线程一直没有停止。
通过JVM命令查看:
在真实的业务中死锁一般不容易察觉!
代码示例:
package imooc4.lock.deadlock;/*** @Description:*/
public class Coupon {private String id;private String displayName;private Long amount;private Member member;public synchronized Long getAmount(){return this.amount;}public synchronized void setAmount(Long amount) throws InterruptedException {this.amount = amount;if(amount==0){Thread.sleep(1000);//从member移除这个优惠券member.removeCoupon(id);}}public String getId() {return id;}public Coupon(String id, String displayName, Long amount, Member member) {this.id = id;this.displayName = displayName;this.amount = amount;this.member = member;}
}
package imooc4.lock.deadlock;import java.util.ArrayList;
import java.util.List;/*** @Description:*/
public class Member {private String id;private String name;private String address;private List<Coupon> coupons;public synchronized void removeCoupon(String id) {this.coupons.removeIf(coupon -> id.equals(coupon.getId()));}public String getId() {return id;}public synchronized Long getAllCouponsAmount() throws InterruptedException {Long result = 0L;Thread.sleep(1000);for (Coupon coupon : coupons) {result+=coupon.getAmount();}return result;}public Member(String id, String name, String address) {this.id = id;this.name = name;this.address = address;}public void setCoupons(List<Coupon> coupons) {this.coupons = coupons;}
}
package imooc4.lock.deadlock;import java.util.ArrayList;
import java.util.List;/*** @Description:*/
public class TestMember {public static void main(String[] args) throws InterruptedException {//构建对象Member member = new Member("1","慕课","北京");Coupon coupon = new Coupon("1","coupon1",200L,member);Coupon coupon1 = new Coupon("2","coupon2",150L,member);Coupon coupon2 = new Coupon("3","coupon3",100L,member);List<Coupon> couponList = new ArrayList<>();couponList.add(coupon);couponList.add(coupon1);couponList.add(coupon2);member.setCoupons(couponList);Thread thread = new Thread(() -> {try {coupon.setAmount(0L);} catch (InterruptedException e) {throw new RuntimeException(e);}});Thread thread1 = new Thread(() -> {try {Long allCouponsAmount = member.getAllCouponsAmount();} catch (InterruptedException e) {throw new RuntimeException(e);}});thread.start();thread1.start();thread.join();thread1.join();System.out.println("运行结束");}
}
11.(死锁)形成死锁的条件与如何避免死锁?
优化代码:
package imooc4.lock.deadlock;/*** @Description:*/
public class Coupon {private String id;private String displayName;private Long amount;private Member member;public synchronized Long getAmount(){return this.amount;}public void setAmount(Long amount) throws InterruptedException {synchronized(this){this.amount = amount;}if(amount==0){Thread.sleep(1000);//从member移除这个优惠券member.removeCoupon(id);}}public String getId() {return id;}public Coupon(String id, String displayName, Long amount, Member member) {this.id = id;this.displayName = displayName;this.amount = amount;this.member = member;}
}
package imooc4.lock.deadlock;import java.util.ArrayList;
import java.util.List;/*** @Description:*/
public class Member {private String id;private String name;private String address;private List<Coupon> coupons;public synchronized void removeCoupon(String id) {this.coupons.removeIf(coupon -> id.equals(coupon.getId()));}public String getId() {return id;}public synchronized Long getAllCouponsAmount() throws InterruptedException {Long result = 0L;Thread.sleep(1000);List<Coupon> temps = new ArrayList<>(coupons);for (Coupon coupon : temps) {result+=coupon.getAmount();}return result;}public Member(String id, String name, String address) {this.id = id;this.name = name;this.address = address;}public void setCoupons(List<Coupon> coupons) {this.coupons = coupons;}
}
package imooc4.lock.deadlock;import java.util.ArrayList;
import java.util.List;/*** @Description:*/
public class TestMember {public static void main(String[] args) throws InterruptedException {//构建对象Member member = new Member("1","慕课","北京");Coupon coupon = new Coupon("1","coupon1",200L,member);Coupon coupon1 = new Coupon("2","coupon2",150L,member);Coupon coupon2 = new Coupon("3","coupon3",100L,member);List<Coupon> couponList = new ArrayList<>();couponList.add(coupon);couponList.add(coupon1);couponList.add(coupon2);member.setCoupons(couponList);Thread thread = new Thread(() -> {try {coupon.setAmount(0L);} catch (InterruptedException e) {throw new RuntimeException(e);}});Thread thread1 = new Thread(() -> {try {Long allCouponsAmount = member.getAllCouponsAmount();} catch (InterruptedException e) {throw new RuntimeException(e);}});thread.start();thread1.start();thread.join();thread1.join();System.out.println("运行结束");}
}
运行结果:
12.(活锁)什么是活锁与如何避免活锁的发生?
活锁是为了解决死锁问题才发生的!
活锁能解决大部分死锁问题,但是极端情况,刚开始所有人左手拿餐叉,等待10秒后,所有人都放弃左手拿餐叉,都改为右手拿餐叉,结果又导致互斥。