观看“尚硅谷”相关视频自己记录的笔记!
1.Synchronized关键字实现买票案例
class Ticket {
public int number = 30;
public synchronized void sale() {
if (number > 0) {
System.out.println(Thread.currentThread().getName() + " : 卖出 : " + (number--) + " ,剩下 : " + number);
}
}
}
public class SaleTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 30; i++) {
ticket.sale();
}
}
}, "AA").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 30; i++) {
ticket.sale();
}
}
}, "BB").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 30; i++) {
ticket.sale();
}
}
}, "CC").start();
}
}
2.Lock接口实现买票案例
class Ticket {
public int number = 30;
private final ReentrantLock lock = new ReentrantLock();
public void sale() {
lock.lock();
try {
if (number > 0) {
System.out.println(Thread.currentThread().getName() + " : 卖出 : " + (number--) + " ,剩下 : " + number);
}
} finally {
lock.unlock();
}
}
}
public class LSaleTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(() -> {
for (int i = 0; i < 30; i++) {
ticket.sale();
}
}, "AA").start();
new Thread(() -> {
for (int i = 0; i < 30; i++) {
ticket.sale();
}
}, "BB").start();
new Thread(() -> {
for (int i = 0; i < 30; i++) {
ticket.sale();
}
}, "CC").start();
}
}
3.“虚假唤醒”问题
**在哪里等待就在哪里醒来!!**
**加上while()循环!**
class share {
private int num = 0;
public synchronized void incr() throws InterruptedException {
while (num != 0) {
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName() + " :: " + num);
this.notifyAll();
}
public synchronized void decr() throws InterruptedException {
while (num != 1) {
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName() + " :: " + num);
this.notifyAll();
}
}
public class ThreadDemo1 {
public static void main(String[] args) {
share s = new share();
new Thread(() -> {
for (int i = 0; i < 30; i++) {
try {
s.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "AA").start();
new Thread(() -> {
for (int i = 0; i < 30; i++) {
try {
s.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "BB").start();
new Thread(() -> {
for (int i = 0; i < 30; i++) {
try {
s.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "CC").start();
new Thread(() -> {
for (int i = 0; i < 30; i++) {
try {
s.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "DD").start();
}
}
4.定制化实现买票案例
**AA卖5次票**
**BB卖10次票**
**CC卖15次票**
**执行十轮**
class ShareResource {
private int flag = 1;
private Lock lock = new ReentrantLock();
private Condition c1 = lock.newCondition();
private Condition c2 = lock.newCondition();
private Condition c3 = lock.newCondition();
public void print5(int loop) throws InterruptedException {
lock.lock();
try {
while (flag != 1) {
c1.await();
}
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " :: " + i + " :轮数: " + loop);
}
flag = 2;
c2.signal();
} finally {
lock.unlock();
}
}
public void print10(int loop) throws InterruptedException {
lock.lock();
try {
while (flag != 2) {
c2.await();
}
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " :: " + i + " :轮数: " + loop);
}
flag = 3;
c3.signal();
} finally {
lock.unlock();
}
}
public void print15(int loop) throws InterruptedException {
lock.lock();
try {
while (flag != 3) {
c3.await();
}
for (int i = 0; i < 15; i++) {
System.out.println(Thread.currentThread().getName() + " :: " + i + " :轮数: " + loop);
}
flag = 1;
c1.signal();
} finally {
lock.unlock();
}
}
}
public class ThreadDemo3 {
public static void main(String[] args) {
ShareResource shareResource = new ShareResource();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
shareResource.print5(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "AA").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
shareResource.print10(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "BB").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
shareResource.print15(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "CC").start();
}
}
5.synchronize实现同步的基础
Java中的每一个对象都可以作为锁。
对于普通同步方法,锁是当前实例对象。
对于静态方法,锁是当前类的Class对象。
对于同步方法块,锁是synchonized括号里配置的对象。
6.多线程锁
公平锁 :阳光普照 效率低
非公平锁 :线程饿死 效率高
7.可重入锁
synchronized(隐式)和lock(显式)都是可重入锁 :是否需要手动上锁解锁操作!
lock实现可重入锁
new Thread(() -> {
try {
lock.lock();
System.out.println(Thread.currentThread().getName());
try {
lock.lock();
System.out.println(Thread.currentThread().getName());
}finally {
lock.unlock();
}
}finally {
lock.unlock();
}
}, "AA").start();
8、死锁
static Object a = new Object();
static Object b = new Object();
public static void main(String[] args) {
new Thread(()->{
synchronized (a) {
System.out.println(Thread.currentThread().getName() + "持有锁a,试图获取锁b");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b) {
System.out.println(Thread.currentThread().getName() + "获取锁b");
}
}
},"A").start();
new Thread(()->{
synchronized (b) {
System.out.println(Thread.currentThread().getName() + "持有锁b,试图获取锁a");
synchronized (a) {
System.out.println(Thread.currentThread().getName() + "获取锁a");
}
}
},"B").start();
}
9.“FutureTask”原理
先执行子线程,最后汇总!
class MyThread1 implements Runnable {
@Override
public void run() {
return;
}
}
class MyThread2 implements Callable {
@Override
public Integer call() throws Exception {
return 200;
}
}
public class Demo01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> task1 = new FutureTask<Integer>(new MyThread2());
FutureTask<Integer> task2 = new FutureTask<Integer>(() -> {
System.out.println(Thread.currentThread().getName() + " come in callable");
return 1024;
});
new Thread(task2,"lucy").start();
while(!task2.isDone()) {
System.out.println("wait...");
}
System.out.println(task2.get());
System.out.println(task2.get()); //不用等待,直接获取!
System.out.println(Thread.currentThread().getName() + " come over");
}
}
10.JUC辅助类
CountDownLatch
所有同学离开之后,班长锁门!!!
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(6);
for(int i = 1; i <= 6;i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + " 号同学离开了教室");
latch.countDown();
},String.valueOf(i)).start();
}
latch.await();
System.out.println(Thread.currentThread().getName() + " 班长锁门走人了!");
}
CylicBarrier
所有条件实现之后,然后干。。。。
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(number, () -> {
System.out.println("***********七颗龙珠已经集齐,可以召唤神龙!");
});
for (int i = 1; i <= 7; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " 星龙珠获得");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
Semaphore
public static void main(String[] args) {
//设置许可数量
Semaphore semaphore = new Semaphore(3);
//模拟六辆汽车
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
try {
//抢占
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " 号车抢到了车位!");
//设置随机停车时间
TimeUnit.SECONDS.sleep(new Random().nextInt(5));
System.out.println(Thread.currentThread().getName() + " 号车-离开了车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
11.读写锁
读写锁 :一个资源可以被多个读线程访问,或者可以被一个写线程访问,但是不能同时存在读写线程。读写互斥,读读共享!
ReentrantReadWriteLock
读读可以共享,提升性能!
同时进行读操作!
缺点 :(1)造成锁饥饿,一直读,没有写操作。
(2)读时候,不能写,只有读完成之后,才可以写,写操作可以读。
//资源类
class MyCache {
//创建map集合
private volatile Map<String, Object> map = new HashMap<>();
private ReadWriteLock lock = new ReentrantReadWriteLock();
//存数据
public void put(String key, Object value) throws InterruptedException {
lock.writeLock().lock();
System.out.println(Thread.currentThread().getName() + " 正在写 " + key);
TimeUnit.MICROSECONDS.sleep(300);
map.put(key, value);
System.out.println(Thread.currentThread().getName() + " 写完了 " + key);
lock.writeLock().unlock();
}
//取数据
public Object get(String key) throws InterruptedException {
lock.readLock().lock();
Object result = null;
System.out.println(Thread.currentThread().getName() + " 正在取 " + key);
TimeUnit.MICROSECONDS.sleep(300);
result = map.get(key);
System.out.println(Thread.currentThread().getName() + " 取完了 " + key);
lock.readLock().unlock();
return result;
}
}
public class ReadAndWriteDemo {
//创建线程存数据
public static void main(String[] args) {
MyCache cache = new MyCache();
for (int i = 1; i <= 5; i++) {
final int num = i;
new Thread(() -> {
try {
cache.put(num + "", num + "");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
try {
TimeUnit.MICROSECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
//创建线程取数据
for (int i = 1; i <= 5; i++) {
final int num = i;
new Thread(() -> {
try {
cache.get(num + "");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
}
读写锁降级
写锁 -> 读锁 -> 写锁释放 -> 读锁释放
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
//获取写锁
writeLock.lock();
System.out.println("---write");
//获取读锁
readLock.lock();
System.out.println("---read");
//释放写锁
writeLock.unlock();
//释放读锁
readLock.unlock();