Juc学习

一、基础回顾

实现线程的三种方式,1.继承thread 2.实现runnable 3.实现callable接口
进程与线程:线程是进程的最小单位
java默认有几个线程:main,gc
java可以开启线程吗?java开启不了,是调用三方库
并发与并行: 在这里插入图片描述

线程有几个状态:Thread.state
wait/sleep的区别:
1.来自不同的类 wait -->object sleep–>thread
2.关于锁的释放: wait释放锁 sleep不释放锁
3.使用范围不同: wait 必须在同步代码块中使用,sleep没有限制

真正的多线程开发,公司里面的开发,线程是一个单独的资源类,没有任务附属的操作(OOP)

二、Synchronized

本质:队列,锁

1. synchronized和locked的区别

在这里插入图片描述

2.生产者消费者模式 新版和老版本

/**
 * 生产者消费者  老版
 * 三步:判断等待,业务,唤醒
 */
public class OldProductAndCustomerTest {

    public static void main(String[] args) {
        A a = new A();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                a.product();
            }
        },"a").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                a.customer();
            }
        },"b").start();
    }

}
class A{

    private int number=0;

    public synchronized void product(){

        try {
            while(number !=0){
                this.wait();
            }
            number=number+1;
            System.out.println(Thread.currentThread().getName()+"  number -->"+number);
            this.notifyAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return;
    }

    public synchronized void customer(){
        try {
            while (number==0){
                this.wait();
            }
            number = number-1;
            System.out.println(Thread.currentThread().getName()+"  number -->"+number);
            this.notifyAll();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

/**
 * 生产者消费者  新版
 * 三步:判断等待,业务,唤醒
 */
public class NewProductAndCustomerTest {

    public static void main(String[] args) {
        B b = new B();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                b.product();
            }
        },"a").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                b.customer();
            }
        },"b").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                b.product();
            }
        },"c").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                b.customer();
            }
        },"d").start();
    }

}

class B{

    private int number=0;
    private Lock lock= new ReentrantLock();
    private Condition condition = lock.newCondition();
    public  void product(){
        lock.lock();

        try {
            while(number !=0){
                condition.await();
            }
            number=number+1;
            System.out.println(Thread.currentThread().getName()+"  number -->"+number);
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

        return;
    }

    public  void customer(){
        lock.lock();
        try {
            while (number==0){
                condition.await();
            }
            number = number-1;
            System.out.println(Thread.currentThread().getName()+"  number -->"+number);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

3.虚假唤醒

在这里插入图片描述

三、Condition实现精准通知唤醒


/**
 * 生产者消费者 精准唤醒
 * 三步:判断等待,业务,唤醒
 */
public class ConditionProductAndCustomerTest {

    public static void main(String[] args) {
        C c = new C();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                c.printA();
            }
        },"a").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                c.printB();
            }
        },"b").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                c.printC();
            }
        },"c").start();
    }

}

class C{

    private int number=1;//1A 2B 3C
    private Lock lock= new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();


    public  void printA(){
        lock.lock();

        try {
            while(number !=1){
                condition1.await();
            }
            number=2;
            System.out.println(Thread.currentThread().getName()+"  number -->AAAAA");
            condition2.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

        return;
    }

    public  void printB(){
        lock.lock();
        try {
            while (number!=2){
                condition2.await();
            }
            number = 3;
            System.out.println(Thread.currentThread().getName()+"  number -->BBBBBB");
            condition3.signal();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public  void printC(){
        lock.lock();
        try {
            while (number!=3){
                condition3.await();
            }
            number = 1;
            System.out.println(Thread.currentThread().getName()+"  number -->CCCCC");
            condition1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

四、八锁现象

锁类,锁对象

五、集合类的不安全解决方案

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、callable

在这里插入图片描述

七、三大辅助类

1.countDownLatch

在这里插入图片描述

2.cyclicBarrier

在这里插入图片描述

3. semaphore

在这里插入图片描述

八、读写锁 ReadWriteLock

在这里插入图片描述
在这里插入图片描述

九、阻塞队列

阻塞队列应用场景:多线程并发处理,线程池!

1.队列的整个家族

在这里插入图片描述
在这里插入图片描述

2.BlockingQueue

在这里插入图片描述

3.队列的四组API

在这里插入图片描述

4.同步队列

在这里插入图片描述

十、线程池

在这里插入图片描述

1.三大方法

在这里插入图片描述

在这里插入图片描述

2.七大参数

在这里插入图片描述

3.四大拒绝策略

在这里插入图片描述

4.CPU密集型和IO密集型

解决池的最大的大小
在这里插入图片描述

十一、forkjoin

ForkJoin是由JDK1.7后提供多线并发处理框架。主要用于并行计算中,和 MapReduce 原理类似,都是把大的计算任务拆分成多个小任务并行计算。
forkjoin的特点工作窃取,每个维护的是双端队列
在这里插入图片描述
在这里插入图片描述

/**
 * 求和计算任务
 * 如何使用forkjoin?
 * 1.forkjoinPool通过它来执行
 * 2.计算任务forkjoinPool.execute(ForkJoinTask task)
 * 3.计算类要继承ForkJoinTask
 */
public class ForkJoinDemo extends RecursiveTask<Long> {

    private Long start ;
    private Long end;
    private Long temp =10000L;

    public ForkJoinDemo(Long start, Long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        if((end-start)<temp){
            Long sum=0L;
            for (Long i = start; i < end; i++) {
                sum += i;
            }
            return sum;
        }else {
            long middle =(end+start)/2;
            ForkJoinDemo task1 = new ForkJoinDemo(start,middle);
            ForkJoinDemo task2 = new ForkJoinDemo(middle+1,end);
            task1.fork();//拆分任务,把任务压入线程队列
            task2.fork();
            return task1.join()+task2.join();
        }

    }
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;

public class ForkJoinTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        test1();
        test2();
//        test3();

    }

    public static void test1(){
        long sum =0;
        long start = System.currentTimeMillis();
        for (long i = 0l; i < 10_0000_0000; i++) {
            sum+=i;
        }
        long end = System.currentTimeMillis();
        System.out.println("sum="+sum+"耗时:"+(end-start));
    }


    public static void test2() throws ExecutionException, InterruptedException {
        long sum =0;
        long start = System.currentTimeMillis();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTask<Long> task = new ForkJoinDemo(0l,10_0000_0000l);
        ForkJoinTask<Long> submit = forkJoinPool.submit(task);
        sum = submit.get();
        long end = System.currentTimeMillis();
        System.out.println("sum="+sum+"耗时:"+(end-start));
    }

    public static void test3(){
        long sum =0;
        long start = System.currentTimeMillis();
        sum = LongStream.rangeClosed(0l,10_0000_0000l).parallel().reduce(0,Long::sum);

        long end = System.currentTimeMillis();
        System.out.println("sum="+sum+"耗时:"+(end-start));
    }
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值