JUC并发编程

观看“尚硅谷”相关视频自己记录的笔记!

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();
上一篇:GUI编程笔记(java)01:GUI和CLI


下一篇:Redis从入门到精通-事物和锁机制-事物冲突(乐观锁和悲观锁)