JUC

1 篇文章 0 订阅

1.卖票 (Lambda表达式)

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

/**
 * @author Liu Qingfeng
 * @create 2021-02-10----21:20
 *
 * 多线程的实现。
 * 
 * 将所有方法都压缩到资源类中,降低耦合
 *
 * 在接口中有且只有一个方法称为函数式接口,可以用Lambda Express
 * 在这个接口上可以显示加上@FunctionalInterface  函数式接口。自己不写,系统会自动默认是@FunctionalInterface
 *
 * 因为只有一个方法所以可以省略方法名。
 *
 * 语法:
 *     () -> {};
 *
 */
public class SaleTest {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();

        new Thread(()->{ for (int i = 0; i < 30; i++) {ticket.saleTicket();} },"AA").start();
        new Thread(()->{ for (int i = 0; i < 30; i++) {ticket.saleTicket();} },"BB").start();
        new Thread(()->{ for (int i = 0; i < 30; i++) {ticket.saleTicket();} },"CC").start();
      /*  new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i<= 30; i++){
                    ticket.saleTicket();
                }
            }
        },"AA").start();            //这里运行到start之后,不会立即执行,表示进入了就绪状态,等待操作系统CPU的空闲

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i<= 30; i++){
                    ticket.saleTicket();
                }
            }
        },"BB").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i<= 30; i++){
                    ticket.saleTicket();
                }
            }
        },"CC").start();*/
    }
}

class Ticket{
    private int ticket = 30;
    private int i = 1;
    private Lock lock= new ReentrantLock();
    public void saleTicket() {
        lock.lock();
        try{
            if (ticket > 0){
                System.out.println(Thread.currentThread().getName() + "卖了第" + i++ + "张票了,还剩" + --ticket);
            }
        }finally {
            lock.unlock();
        }
    }

}

2.线程通信

防止虚假唤醒

import com.sun.corba.se.impl.naming.cosnaming.NamingUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Liu Qingfeng
 * @create 2021-02-12----20:49
 *
 * 题目:现在两个线程,可以操作初始值为零的一个变量,
 * 实现一个线程对该变量加1,一个线程对该变量-1,
 * 实现交替,来10轮,变量初始值为0.
 *      1.高内聚低耦合前提下,线程操作资源类
 *      2.判断/干活/通知
 *
 * 题目2:现在4个线程,可以操作初始值为零的一个变量,
 * 实现两个个线程对该变量加1,两个个线程对该变量-1,
 * 实现加减交替,执行二十轮,变量初始值为0.
 *      1.高内聚低耦合前提下,线程操作资源类
 *      2.判断/干活/通知
 *      3.防止虚假唤醒(判断只能用while,不能用if)
 * 知识小总结:多线程编程套路+while判断
 */
public class SaleTest2 {
    public static void main(String[] args) {
        Number number = new Number();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    number.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();

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

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    number.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    number.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"C").start();


    }
}

class Number{
    private int num = 0;

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

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

}

3.精确通知,顺序访问。Lock

new Reentrantlock().newCondition();


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

/**
 * @author Liu Qingfeng
 * @create 2021-02-16----12:06
 *
 * Lock支持顺序唤醒
 *
 * A、B、C
 */
public class SaleTest2_2 {
    public static void main(String[] args) {
        Number2_2 number2_2 = new Number2_2();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                number2_2.countA();
            }
        },"A").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                number2_2.countB();
            }
        },"B").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                number2_2.countC();
            }
        },"C").start();
    }
}
class Number2_2 {
    private int flag = 1;
    private Lock lock = new ReentrantLock();
    Condition conditionA = lock.newCondition();
    Condition conditionB = lock.newCondition();
    Condition conditionC = lock.newCondition();
    public void countA() {
        lock.lock();
        try {
           while (flag != 1){
               conditionA.await();
           }
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
            flag = 2;
            conditionB.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void countB() {
        lock.lock();
        try {
            while (flag != 2){
                conditionB.await();
            }
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
            flag = 3;
            conditionC.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
    public void countC() {
        lock.lock();
        try {
            while (flag != 3) {
                conditionC.await();
            }
            for (int i = 0; i < 15; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }
            flag = 1;
            conditionA.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
}

4.锁机制

不同的对象,不同的锁。

锁只锁同步方法(Synchronized)。不锁普通方法

静态同步方法,不管是几个对象调用的。都是一个锁

import sun.util.locale.provider.TimeZoneNameUtility;

import java.util.concurrent.TimeUnit;

/**
 * @author Liu Qingfeng
 * @create 2021-02-16----13:12
 */
public class SaleTest3 {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        Phone phone1 = new Phone();
        new Thread(() ->{
            try {
                phone.sendmail();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();

        Thread.sleep(100);

        new Thread(() -> {
            try {
                phone1.hello();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();

    }
}
class Phone {
    public static synchronized void sendmail(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("-----sendmail");
    }
    public static synchronized void hello(){
        System.out.println("----hello");
    }
}

5.集合不安全解决方法

ArrayList

 *      new Vector<>();
 *      Collections.synchronizedList(new ArrayList<String>());
 *      new CopyOnWriteArrayList(); //写时复制

Set
 *      Collections.synchronizedSet(new HashSet<String>());
 *      new CopyOnWriteArraySet(); //写时复制

Map

 *      Collections.synchronizedMap(new HashMap<String,Object>());
 *      new ConcurrentHashMap<String,Object>();


/**
 * 1.故障现象
 * 并发修改异常
 * java.util.ConcurrentModificationException
 * 2.导致原因
 * 3.解决方法
 *      3.1 new Vector<>();
 *      3.2 Collections.synchronizedList(new ArrayList<String>());
 *      3.3 new CopyOnWriteArrayList(); //写时复制
 * 4.优化建议(同样的错误不犯第二次)
 *
 * 写时复制:
 *  CopyOnWrite容器即写时复制的容器。往一个容器添加元素的时候,不直接往当前容器Object[]添加,而是现将当前容器Object[]进行Copy,
 *  复制出一个新的容器Object[] newElements,然后新的容器Object[] newElements里添加元素,添加完元素之后,
 *  再将原容器的引用指向新的容器setArray(newElements);。这样做的好处是可以对CopyOnWrite容器进行并发的读,
 *  而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器
 */
public class NotSafeDemo3 {
    public static void main(String[] args) {
        mapNotSafe();
    }
    public static void mapNotSafe() {
        Map<String,String> map = new ConcurrentHashMap<String, String>();
        for (int i = 1; i <= 30; i++) {
            new Thread(() -> {
                map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));
                System.out.println(map);
            },String.valueOf(i)).start();
        }
    }

    public static void setNotSafe() {
        Set<String> set = new CopyOnWriteArraySet<String>();
        for (int i = 1; i <= 30; i++) {
            new Thread(() -> {
                set.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
    }

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

6.Callable实现

用Callable接口要用他的实现类Future Task。

class MyThread2 implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        System.out.println("******come in call method()");
        return 1080;
    }
}

/**
 * 多线程中,第3种获得多线程的方式
 */
public class CallableDemo7 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask(new MyThread2());

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

        Integer result = futureTask.get();
        System.out.println(result);
    }
}

7.CountDownLatchDemo

import java.util.concurrent.CountDownLatch;

/**
 * @author Liu Qingfeng
 * @create 2021-02-17----11:17
 *
 * 保证主线程在计数完成之后,最后关闭线程。
 */
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);

        for (int i = 0; i < 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t离开教室");
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "\t班长锁门走人");
    }
}

8.CyclicBarrierDemo

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

/**
 * @author Liu Qingfeng
 * @create 2021-02-17----11:23
 */
public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,() -> {
            System.out.println("****召唤神龙");
        });
        for (int i = 1; i <= 7; i++) {
            final int tempInt = i;
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t收集到" + tempInt + "星龙珠");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }
}

9.SemaphoreDemo

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

/**
 * @author Liu Qingfeng
 * @create 2021-02-17----11:41
 *
 * 抢车位
 * 用于资源的并发控制
 */
public class SemaphoreDemo {
    public static void main(String[] args) {

        /*
        * 如果把资源改成1,那就是多线程抢一个资源。等同于Synchronized
        *
        * 如题:多线程抢一个资源,并对资源持有20s。
        *
        * */
        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(3);  //停三秒离开
                    System.out.println(Thread.currentThread().getName() + "\t离开了车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();
                }
            },String.valueOf(i)).start();
        }

    }
}

10.线程池

 

阻塞和不阻塞的区别
阻塞唤醒的时候会有上下文的切换
CPU时间片的切换


自旋锁就是通过cas算法自选,进行比较

自旋是为了避免阻塞唤醒,需要操作系统切换CPU状态,需要消耗一定时间。

为什么说线程上下文切换消耗资源

1.CPU系统的状态由用户态切换到内核态
2.保存上一个线程执行的指令指针写回到内存块,然后切换到一个新的线程,重新计算,并且在新的线程计算完了之后,还要把上次中断的线程,把他的中间变量再都会cpu,重新的回到中断的状态,再执行。。。
Collections.synchronizedSet(new HashSet<String>());

隐式锁synchronized
显式锁,上锁和解锁都要显式处理Reentrantlock

synchronized和实现了lock接口的都是悲观锁


ReentrantReadWriteLock.ReadLock算是一种乐观锁。

import java.util.concurrent.*;

/**
 * @author Liu Qingfeng
 * @create 2021-02-16----17:51
 */
public class ThreadPoolTest {
    public static void main(String[] args) {
//        //建五个线程
//        ExecutorService threadPool = Executors.newFixedThreadPool(5);
//
//        //建一个线程
//        ExecutorService threadPool1 = Executors.newSingleThreadExecutor();
//
//        //建可扩容个线程
//        ExecutorService threadPool2 =  Executors.newCachedThreadPool();

        ExecutorService threadPool = new ThreadPoolExecutor(
                2,
                4,
                2L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy()
        ) ;

        try {
            //模拟十个用户办理业务
            for (int i = 0; i < 10; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "办理业务");
                });
            }
        }catch (Exception exception){
            exception.printStackTrace();
        }finally {
            threadPool.shutdown();
        }
    }
}

11.阻塞队列

 

四大函数式接口

12.volitial

13.Java锁

 

CAS

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值