JUC学习笔记(一)

JUC学习笔记(一)

  • 多线程售票问题
  • 线程的六种状态
  • 集合类安全问题
  • 8锁问题
  • 消费者生产者模型
  • ConditionDemo
  • Callable
  • CountdownLatch
  • CyclicBarrier
  • Semaphore
  • ReadWriteLock
  • BlockingQueue

多线程售票问题

package com.Test;

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

class Ticket{
    private int number = 30;
    Lock lock = new ReentrantLock();

	//卖票方法
    public void sale(){
        lock.lock();
        try {
            if(number > 0){
                System.out.println(Thread.currentThread().getName() + "卖出第" +number-- + "票,剩余" + number+ "张");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

//卖票
public class SaleTicketDemo {
    public static void main(String agrs[]){

        Ticket ticket = new Ticket();

        new Thread(()->{
            for(int i = 1; i <= 40;i++){
                ticket.sale();
            }
        },"售票员A").start();
        new Thread(()->{
            for(int i = 1; i <= 40;i++){
                ticket.sale();
            }
        },"售票员B").start();
        new Thread(()->{
            for(int i = 1; i <= 40;i++){
                ticket.sale();
            }
        },"售票员C").start();
    }
}

线程的六种状态

public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * 
    *
  • {@link Object#wait() Object.wait} with no timeout
  • *
  • {@link #join() Thread.join} with no timeout
  • *
  • {@link LockSupport#park() LockSupport.park}
  • *
* *

A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called Object.wait() * on an object is waiting for another thread to call * Object.notify() or Object.notifyAll() on * that object. A thread that has called Thread.join() * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: *

    *
  • {@link #sleep Thread.sleep}
  • *
  • {@link Object#wait(long) Object.wait} with timeout
  • *
  • {@link #join(long) Thread.join} with timeout
  • *
  • {@link LockSupport#parkNanos LockSupport.parkNanos}
  • *
  • {@link LockSupport#parkUntil LockSupport.parkUntil}
  • *
*/
TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }

集合类安全问题

/*
*
* 1 java.util.ConcurrentModificationException 并发修改异常
*
* 2 解决方法 List: (1)Vector()
*                 (2)Collection.synchronizedList(new ArrayList())
*                 (3)CopyOnWriteArrayList()
*
*   解决方法 Set:  (1)Collection.synchronizedList(new HashSet())
*                 (2)CopyOnWriteHashSet()
*
*   解决方法 HashMap: ConcurrentHashMap()
*
* */
public class ListNotSafeDemo {
    public static void main(String args[]){
        List<String> list = new ArrayList<>();

        for(int i = 0;i <= 30; i++){
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

/*
* CopyOnWriteArrayList<>的add()方法
*   1.使用lock方式加锁
*   2.创建一个长度比原数组length长1的新的数组
*   3.将原数组拷贝到新数组,将添加的元素放到数组最后一格
* */
public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

8锁问题

package com.Test;

import java.util.concurrent.TimeUnit;

class Phone {
    public static void sendEmail() throws Exception {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("*****sendEmail*****");
    }

    public static synchronized void sendSMS() throws Exception {
        System.out.println("*****sendSMS*****");
    }

    public void sayHello() throws Exception{
        System.out.println("****sayHello****");
    }
}

public class Lock8Demo {
    /*
     * 8lock
     *
     * 1.标准访问,先打印邮件还是短信
     * 2.邮件暂停4s,先打印邮件还是短信
     * 3.新增普通sayHello()方法,先打印哪个
     * 4.两部phone,先打印哪个 短信 邮件
     * 5.两个静态同步方法,同意一部手机,请问先打印短息还是邮件
     * 6.两个静态同步方法,2部手机,请问先打印邮件还是短信
     * 7.1个静态同步方法,1个普通同步方法,同意一部手机,请问先打印邮件还是短信
     * 8.一个静态同步方法,一个普通同步方法,同意一部手机,先打印邮件还是短信
     *
     *  锁的是当前对象this,被锁定后,某一时刻内,只能有唯一一个线程去访问这些synchronized方法
     *
     *  同步方法与同步锁无关
     *  换成两个对象后,不是同一把锁,情况改变,换成静态同步方法后,锁的是当前类,情况又改变
     *
     *  synchronized实现同步的基础:Java中的每一个对象都可以作为锁
     *      (1)对于普通同步方法,锁的是当前实例对象,锁的是当前对象this
     *      (2)对于同步方法块,锁是synchonized括号里配置的对象
     *      (3)对于静态同步方法,锁的是当前类的class对象
     * */
    public static void main(String args[]) throws Exception{
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        new Thread(()->{
            try {
                phone.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{
            try {
                phone.sendSMS();
//                phone.sayHello();
//                phone2.sendSMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"B").start();
    }
}

消费者生产者模型

package com.Test;

class Aicondition{
    private int number = 0;

    public synchronized void increment() throws Exception{
        while(number != 0){
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName()+"\t" + number);
        this.notifyAll();
    }

    public synchronized void decrement() throws Exception{
        while(number == 0){
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName()+"\t" + number);
        this.notifyAll();
    }
}

/*
*
* 多个线程操作一个初始值为0的变量,使其交替打印0和1
* 1高内聚、低耦合,线程操作资源类
* 2判断、工作、通知
* 3防止虚假唤醒 多线程中的判断要使用while代替if重新做条件判断
*
**/
public class ProducerConsumerDemo {

    public static void main(String args[]){
        Aicondition aicondition = new Aicondition();

        new Thread(()->{
            for(int i = 1;i <= 10; i++){
                try {
                    aicondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"A").start();

        new Thread(()->{
            for(int i = 1;i <= 10; i++){
                try {
                    aicondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"B").start();
        new Thread(()->{
            for(int i = 1;i <= 10; i++){
                try {
                    aicondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"C").start();

        new Thread(()->{
            for(int i = 1;i <= 10; i++){
                try {
                    aicondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"D").start();
    }
}

ConditionDemo

package com.Test;

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

class ShareData{
    private int number = 1;
    private Lock lock = new ReentrantLock();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();

    public void print5(){
        lock.lock();
        try{
            //1.判断
            while (number != 1) {
                c1.await();
            }
            //2.工作
            for (int i = 1; i <= 5; i++) {
                System.out.println(Thread.currentThread().getName()+"\t"+i);
            }
            number = 2;
            c2.signal();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print10(){
        lock.lock();
        try{
            //1.判断
            while (number != 2) {
                c2.await();
            }
            //2.工作
            for (int i = 1; i <= 10; i++) {
                System.out.println(Thread.currentThread().getName()+"\t"+i);
            }
            number = 3;
            c3.signal();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void print15(){
        lock.lock();
        try{
            //1.判断
            while (number != 3) {
                c3.await();
            }
            //2.工作
            for (int i = 1; i <= 15; i++) {
                System.out.println(Thread.currentThread().getName()+"\t"+i);
            }
            number = 1;
            c1.signal();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

/*
* 多线程之间按顺序调用,实现A->B->C
*
*
*
* */
public class ConditionDemo {
    public static void main(String args[]){
        ShareData shareData = new ShareData();
        new Thread(()->{
            for(int i = 0; i < 5; i++){
                shareData.print5();
            }
        },"A").start();

        new Thread(()->{
            for(int i = 0; i < 5; i++){
                shareData.print10();
            }
        },"B").start();

        new Thread(()->{
            for(int i = 0; i < 5; i++){
                shareData.print15();
            }
        },"C").start();
    }
}

Callable

package com.Test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

class MyThread implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        System.out.println("*****COME IN CALL METHOD()*****");
        return 1024;
    }
}

public class CallableDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask futureTask = new FutureTask(new MyThread());

        new Thread(futureTask,"A").start();

        Integer result = (Integer)futureTask.get();

        System.out.println(result);
    }
}

CountdownLatch

当执行足够的次数后,才能继续执行

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {

    public static void main(String[] args) throws InterruptedException {
        
        //设置次数为6次
        CountDownLatch countDownLatch = new CountDownLatch(6);

        for (int i = 1; i <= 6; i++) {
            new Thread(()->{
                //计数,执行一次改行代码,计数一次
                countDownLatch.countDown();
                System.out.println(Thread.currentThread().getName() + "\t离开教室");
            },String.valueOf(i)).start();
        }
        //等待,执行足够的次数后,才能执行后续代码(设定次数为6次)
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "\t关门");
    }

    public static void closeDoor(){
        for(int i = 1; i <= 6; i++){
            new Thread(()->{
                System.out.println(Thread.currentThread().getName() + "\t离开教室");
            },String.valueOf(i)).start();
        }
    }
}

CyclicBarrier

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {
    public static void main(String[] args){
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
            System.out.println("人齐开会");
        });

        for(int i = 1; i <= 7; i++){
            new Thread(()->{
                System.out.println(Thread.currentThread().getName() +"\t到场");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }
}

Semaphore

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/*

* 信号量主要用于两个目的:
* 1.用于多个共享资源的互斥作用
* 2.用于并发线程数的控制
*
* */
public class SemaphoreDemo {
    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()+"\t抢占到了车位");
                    TimeUnit.SECONDS.sleep(2);
                    System.out.println(Thread.currentThread().getName()+"\t离开了车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                }

            },String.valueOf(i)).start();
        }
    }
}

ReadWriteLock

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

class MyCache{

    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private volatile Map<String,Object> map = new HashMap<>();

    public void put(String key,Object value) throws InterruptedException {
        readWriteLock.writeLock().lock();
        try{
            System.out.println(Thread.currentThread().getName() + "\t 写入数据" + key);
            TimeUnit.SECONDS.sleep(1);
            map.put(key,value);
            System.out.println(Thread.currentThread().getName() + "\t 写入完成" + key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }

    public void get(String key) throws InterruptedException {
        readWriteLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "\t 读取数据");
            TimeUnit.SECONDS.sleep(1);
            map.get(key);
            System.out.println(Thread.currentThread().getName() + "\t 读取数据");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.readLock().unlock();
        }
    }
}

/*
* 多个线程同时读取一个资源类没有问题,为了满足并发量需求,读取共享资源可以同时进行
* 但是如果有一个线程写共享资源,就不应该再有其他线程对该资源读或写
*
* 读-读 共存
* 读-写 不共存
* 写-写 不共存
* */
public class ReadWriteLockDemo {
    public static void main(String[] args){
        MyCache myCache = new MyCache();
        for(int i = 1; i <= 5; i++){
            final int tempInt = i;
            new Thread(()->{
                try {
                    myCache.put(tempInt+"",tempInt+"");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
        for(int i = 1; i <= 5; i++){
            final int tempInt = i;
            new Thread(()->{
                try {
                    myCache.get(tempInt+"");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }
}

BlockingQueue

import java.util.Collection;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

/*
* 当队列是空的,从队列中获取元素的操作将会被堵塞
* 当队列是满的,从队列中添加元素的操作将会被阻塞
*
* BlockingQueue核心方法
* 插入: add() 队满时异常IllegalStateException
*       offer() 队满时插入失败,返回false
*       put() 队满时阻塞,直到插入成功
*       offer(e,time,TimeUnit) 队满时,等待一定时间,如果插入成功返回true,
*   如果仍然队满,返回false
*
* 移除: remove() 空队时异常NoSuchElementException
*       poll() 空队移除时返回null
*       take() 空队时阻塞,直到拿到元素
*       poll(time,TimeUnit) 队时空,等待一定时间,如果读取成功返回元素,
*   如果仍然队空,返回null
*
* 检查:element() 查看队首元素
* */
public class BlockingQueueDemo {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        /*
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));

        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        */
/*
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.element());

        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("a"));*/
/*
        blockingQueue.put("a");
        blockingQueue.put("a");
        blockingQueue.put("a");
        blockingQueue.put("a");*/

        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("a", 3, TimeUnit.SECONDS));
    }
}

尚硅谷JUC课程学习笔记

你可能感兴趣的:(JUC学习笔记(一))