juc基础

回顾多线程

线程的六个状态

 //获取CPU的核数
        System.out.println(
                Runtime.getRuntime()
                .availableProcessors()
        );
//Thread 的六种状态,枚举
        Thread.State.values()        
public enum State {
        
        NEW,
 
        RUNNABLE,

         
        BLOCKED,

        
        WAITING,

        
        TIMED_WAITING,
 
        TERMINATED;
    }

操作系统层面是 5个, java 定义了 6个

wait 和 sleep区别

1.锁的释放

  1. wait释放锁,sleep抱着锁睡觉,不释放

2.使用范围不同

  1. wait必须在同步代码块中
  2. sleep可以在任意一个地方睡
  3. 是否需要捕获异常(wait不用捕获异常,sleep必须捕获异常)

3. lock

在这里插入图片描述

3. Synchronized 和 lock的区别

  1. synchronized 是内置的java关键字, Lock是一个java类
  2. Synchronized 无法判断获取锁的状态,Lock 可以判断是否获取到了锁
  3. Synchronized 全自动释放锁
  4. lock必须手动释放锁,不然就是死锁
  5. lock锁有一个 tryLock的方法,可以尝试获取锁(可以判断锁的状态),不一定像Synchronized锁一样,一直阻塞下去
  6. Synchronized 可重入锁,不可以中断,非公平; lock,可重入,不可以中断,非公平(也可以改成公平锁),相比之下,lock比较灵活

线程中的协作问题!!(生产者和消费者的协作)

package example;



/**
 * @Author lyr
 * @create 2020/5/29 19:01
 */
public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        Resource s = new Resource();
        new Thread(()->{
            for(int i=0;i<10;++i) {
                s.incr();
            }
        },"A线程").start();
        new Thread(()->{
            for(int j=0;j<10;++j) {
                s.decr();
            }
        },"B线程").start();
    }

    static class Resource {
        private int number;
        // private Object monitor;
        public synchronized void incr()   {
            while (number>0) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.number++;
            System.out.println("A线程 "+number);
            this.notifyAll();
        }
        public synchronized void decr()   {
            while (number<=0) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.number--;
            System.out.println("B线程 "+number);
            this.notifyAll();
        }
    }
}


4.线程的协作

在这里插入图片描述

使用Condition 的优势!

Condition 可以代替 signal 随机分布,也可以是的线程有序执行,即 你可以使用 condition 精准的通知线程

有序执行。

package example;


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

/**
 * @Author lyr
 * @create 2020/5/29 19:01
 */
public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        Resource s = new Resource();
        new Thread(()->{
            for(int i=0;i<10;++i) {
                s.printA();
            }
        },"A线程").start();
        new Thread(()->{
            for(int j=0;j<10;++j) {
                s.printB();
            }
        },"B线程").start();
        new Thread(()->{
            for(int j=0;j<10;++j) {
                s.printC();
            }
        },"C线程").start();
    }

    static class Resource {
        private int number = 1;
        private Lock lock = new ReentrantLock();
        private Condition conditionA = lock.newCondition();
        private Condition conditionB = lock.newCondition();
        private Condition conditionC = lock.newCondition();

        public  void printA()   {
            lock.lock();
            try{
                while (number!=1) {
                    conditionA.await();
                }
                System.out.println(
                        Thread.currentThread().getName()
                );
                number = 2;
                conditionB.signal();
            }catch (Exception ex) {
                System.out.println(ex);
            }finally {
                lock.unlock();
            }
        }
        public void printB() {
            lock.lock();
            try{
                while (number!=2) {
                    conditionB.await();
                }
                System.out.println(
                        Thread.currentThread().getName()
                );
                number = 3;
                conditionC.signal();
            }catch (Exception ex) {
                System.out.println(ex);
            }finally {
                lock.unlock();
            }
        }

        public void printC() {
            lock.lock();
            try{
                while (number!=3) {
                    conditionC.await();
                }
                System.out.println(
                        Thread.currentThread().getName()
                );
                number = 1;
                conditionA.signal();
            }catch (Exception ex) {
                System.out.println(ex);
            }finally {
                lock.unlock();
            }
        }

    }
}

copyOnWriteArrayList

copyOnwrite 采用写入时复制,读写分离的方式。
只在写操作的时候加锁。

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();
        }
    }
    
    
    final void setArray(Object[] a) {
        array = a;
    }

我们先试试在多线程中打印 操作 ArrayList

并发修改异常

package example;


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

/**
 * @Author lyr
 * @create 2020/5/29 19:01
 */
public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        List list = new ArrayList<>();

        for(int i=1;i<10;++i) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString());
                System.out.println(list);
            }).start();
        }

    }


}

null, d43b5115-f131-4a9a-8c17-685d1463c298, e3a0ddf5-1906-4b86-9367-6b2c46313139, 42143054-8fb2-4810-a6b2-73ee99325b04, f9579c0e-144b-4b28-8ee4-b0d92fb1c63d, 48d97a2c-59e1-4b96-823e-ed41aae01703, 9bfdddc9-e3df-4757-bfc0-cc62408f57d5]
[null, d43b5115-f131-4a9a-8c17-685d1463c298, e3a0ddf5-1906-4b86-9367-6b2c46313139, 42143054-8fb2-4810-a6b2-73ee99325b04, f9579c0e-144b-4b28-8ee4-b0d92fb1c63d, 48d97a2c-59e1-4b96-823e-ed41aae01703]
Exception in thread “Thread-4” Exception in thread “Thread-0” Exception in thread “Thread-3” Exception in thread “Thread-6” java.util.ConcurrentModificationException
at java.util.ArrayList I t r . c h e c k F o r C o m o d i f i c a t i o n ( A r r a y L i s t . j a v a : 909 ) a t j a v a . u t i l . A r r a y L i s t Itr.checkForComodification(ArrayList.java:909) at java.util.ArrayList Itr.checkForComodification(ArrayList.java:909)atjava.util.ArrayListItr.next(ArrayList.java:859)
at java.util.AbstractCollection.toString(AbstractCollection.java:461)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at example.Main.lambda$main 0 ( M a i n . j a v a : 19 ) a t j a v a . l a n g . T h r e a d . r u n ( T h r e a d . j a v a : 748 ) j a v a . u t i l . C o n c u r r e n t M o d i f i c a t i o n E x c e p t i o n a t j a v a . u t i l . A r r a y L i s t 0(Main.java:19) at java.lang.Thread.run(Thread.java:748) java.util.ConcurrentModificationException at java.util.ArrayList 0(Main.java:19)atjava.lang.Thread.run(Thread.java:748)java.util.ConcurrentModificationExceptionatjava.util.ArrayListItr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList I t r . n e x t ( A r r a y L i s t . j a v a : 859 ) a t j a v a . u t i l . A b s t r a c t C o l l e c t i o n . t o S t r i n g ( A b s t r a c t C o l l e c t i o n . j a v a : 461 ) a t j a v a . l a n g . S t r i n g . v a l u e O f ( S t r i n g . j a v a : 2994 ) a t j a v a . i o . P r i n t S t r e a m . p r i n t l n ( P r i n t S t r e a m . j a v a : 821 ) a t e x a m p l e . M a i n . l a m b d a Itr.next(ArrayList.java:859) at java.util.AbstractCollection.toString(AbstractCollection.java:461) at java.lang.String.valueOf(String.java:2994) at java.io.PrintStream.println(PrintStream.java:821) at example.Main.lambda Itr.next(ArrayList.java:859)atjava.util.AbstractCollection.toString(AbstractCollection.java:461)atjava.lang.String.valueOf(String.java:2994)atjava.io.PrintStream.println(PrintStream.java:821)atexample.Main.lambdamain 0 ( M a i n . j a v a : 19 ) a t j a v a . l a n g . T h r e a d . r u n ( T h r e a d . j a v a : 748 ) j a v a . u t i l . C o n c u r r e n t M o d i f i c a t i o n E x c e p t i o n a t j a v a . u t i l . A r r a y L i s t 0(Main.java:19) at java.lang.Thread.run(Thread.java:748) java.util.ConcurrentModificationException at java.util.ArrayList 0(Main.java:19)atjava.lang.Thread.run(Thread.java:748)java.util.ConcurrentModificationExceptionatjava.util.ArrayListItr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList I t r . n e x t ( A r r a y L i s t . j a v a : 859 ) a t j a v a . u t i l . A b s t r a c t C o l l e c t i o n . t o S t r i n g ( A b s t r a c t C o l l e c t i o n . j a v a : 461 ) a t j a v a . l a n g . S t r i n g . v a l u e O f ( S t r i n g . j a v a : 2994 ) a t j a v a . i o . P r i n t S t r e a m . p r i n t l n ( P r i n t S t r e a m . j a v a : 821 ) a t e x a m p l e . M a i n . l a m b d a Itr.next(ArrayList.java:859) at java.util.AbstractCollection.toString(AbstractCollection.java:461) at java.lang.String.valueOf(String.java:2994) at java.io.PrintStream.println(PrintStream.java:821) at example.Main.lambda Itr.next(ArrayList.java:859)atjava.util.AbstractCollection.toString(AbstractCollection.java:461)atjava.lang.String.valueOf(String.java:2994)atjava.io.PrintStream.println(PrintStream.java:821)atexample.Main.lambdamain 0 ( M a i n . j a v a : 19 ) a t j a v a . l a n g . T h r e a d . r u n ( T h r e a d . j a v a : 748 ) j a v a . u t i l . C o n c u r r e n t M o d i f i c a t i o n E x c e p t i o n a t j a v a . u t i l . A r r a y L i s t 0(Main.java:19) at java.lang.Thread.run(Thread.java:748) java.util.ConcurrentModificationException at java.util.ArrayList 0(Main.java:19)atjava.lang.Thread.run(Thread.java:748)java.util.ConcurrentModificationExceptionatjava.util.ArrayListItr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList I t r . n e x t ( A r r a y L i s t . j a v a : 859 ) a t j a v a . u t i l . A b s t r a c t C o l l e c t i o n . t o S t r i n g ( A b s t r a c t C o l l e c t i o n . j a v a : 461 ) a t j a v a . l a n g . S t r i n g . v a l u e O f ( S t r i n g . j a v a : 2994 ) a t j a v a . i o . P r i n t S t r e a m . p r i n t l n ( P r i n t S t r e a m . j a v a : 821 ) a t e x a m p l e . M a i n . l a m b d a Itr.next(ArrayList.java:859) at java.util.AbstractCollection.toString(AbstractCollection.java:461) at java.lang.String.valueOf(String.java:2994) at java.io.PrintStream.println(PrintStream.java:821) at example.Main.lambda Itr.next(ArrayList.java:859)atjava.util.AbstractCollection.toString(AbstractCollection.java:461)atjava.lang.String.valueOf(String.java:2994)atjava.io.PrintStream.println(PrintStream.java:821)atexample.Main.lambdamain$0(Main.java:19)
at java.lang.Thread.run(Thread.java:748)

如何让集合操作安全?

  1. vector
  2. List list = Collections.synchronizedList(new ArrayList<>());
  3. CopyOnWriteArrayList 或者其他的一些工具类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值