JUC

一.JUC概述

 java.util.concurrent------>JUC 增加了在并发编程中很常用的工具类。用于定义类似于线程的自定义系统,包括线程池,异步IO和轻量级任务框架;还提供了了用于多线程上下文中的collection实现。

二.volatile,不稳定的,异变的。

三个特征:1.互斥性(原子性)

                  2.内存可见性

                  3.指令重排序

volatile关键字:当多个线程进行操作的时候,可以保证内存中的数据是可见的,对比synchronized是一种较为轻量级的同步策略。

 同步锁synchronize和volatile的区别

(1)synchronize 可以实现互斥性和内存可见性,不能禁止指令重排序

(2)volatile可以实现内存可见性,可以禁止指令重排序但是不能保证原子性。

public class Demo3 extends Thread {
    public volatile boolean flag=false;

    @Override
    public void run() {
        System.out.println("子线程开始执行.......");
        while (true){
            if (flag){
                break;
            }
        }
        System.out.println("子程序结束了");

    }
}
public class Demo4 {
    public static void main(String[] args) throws Exception{
     Demo3 demo1=new Demo3();
     demo1.start();
        System.out.println("输入任意字符结束子线程");
        System.in.read();
        demo1.flag=true;
        System.out.println(demo1.flag);
        System.out.println("主线程结束了");
    }
}

懒汉式单例


public class SingleTon {
    private String name;
    private int age;
    public SingleTon(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    private SingleTon(){}
    private volatile static SingleTon instance;
    public static SingleTon getInstance(){
        if (instance==null){
            synchronized (SingleTon.class){
                if (instance==null){
                    instance=new SingleTon("元宝",22);
                }
            }
        }
        return instance;
    }
}
public class SingleTest {
    public static void main(String[] args) {
        SingleTon singleTon=SingleTon.getInstance();
        SingleTon singleTon2=SingleTon.getInstance();
        SingleTon singleTon3=SingleTon.getInstance();
        System.out.println(singleTon.getName());
        System.out.println(singleTon.hashCode());
        System.out.println(singleTon2.hashCode());
        System.out.println(singleTon3.hashCode());
    }
}

i++的原子性问题

1.i++的操作可以分为三个步骤  :    int temp=i;  int temp2=temp+1;     i=temp2;

2.所谓的原子性就是这三个步骤不可分割。

3.原子变量:原子变量的值,使用volatile修饰,保证了内存可见性;CAS算法保证了数据的原子性。

public class AtomicDemo implements Runnable{
    private int num=0;

    @Override
    public void run() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(++num);
    }
}
public class AtomicTest {
    public static void main(String[] args) {
        AtomicDemo atomicDemo=new AtomicDemo();
        for (int i = 0; i < 10; i++) {
            new Thread(atomicDemo).start();
        }
    }
}

使用原子变量使用i++   主函数跟上面这个一样

public class Demo5 implements Runnable{

    //private int num=0;
    private AtomicInteger atomicinteger=new AtomicInteger(0);

    @Override
    public void run() {
        System.out.println(atomicinteger.getAndIncrement()); //i++
    }

}

CAS算法:硬件对于并发的支持,针对多处理器操作而设计的处理器中的一种特殊指令,用于管理对共享数据的并发访问。

无锁的非阻塞算法

三个操作数:  进行比较的旧预估值A

                        需要读写的内存值 V

                        将写入的更新值 B

当且仅当A==V时,B的值才会赋值给V 否则的话不作任何操作,这个比较跟交换的过程属于原子操作。

 

四.Lock接口

synchronize的缺陷:a.获取锁的线程如果因为某些原因不能释放锁,其他线程就只能等待

                                 b.使用同一把锁会进入同一个等待队列,所以需要唤醒所有线程

                                 c.无法实现读写锁操作

案列 实现三个线程交替输出20遍ABC

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

public class Alternative {
    private Lock lock=new ReentrantLock();
    private int num=1;
    private int count=1;
    Condition conditionA=lock.newCondition();
    Condition conditionB=lock.newCondition();
    Condition conditionC=lock.newCondition();
    public void printA(){
        lock.lock();
        try {
            if (num!=1){
                try {
                    conditionA.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.print("A");
            num=2;
            conditionB.signal();
        } finally {
            lock.unlock();
        }
    }
    public void printB(){
        lock.lock();
        try {
            if (num!=2){
                try {
                    conditionB.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.print("B");
            num=3;
            conditionC.signal();
        } finally {
            lock.unlock();
        }
    }
    public void printC(){
        lock.lock();
        try {
            if (num!=3){
                try {
                    conditionC.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.print("C");
            System.out.println("-----------"+count+"----------");
            num=1;
            count++;
            conditionA.signal();
        } finally {
            lock.unlock();
        }
    }
}
public class AlternativeTest {
    public static void main(String[] args) {
        Alternative alternative=new Alternative();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    alternative.printA();
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    alternative.printB();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    alternative.printC();
                }
            }
        }).start();
    }
}

五.并发集合

List和Set集合

        CopyOnWriteArrayList 相当于线程安全的ArrayList  实现List接口 支持高并发的; CopyOnWriteArraySet相当于线程安全的HashSet,它继承了AbstractSet类。

        CopyOnWriteArraySet内部包含一个CopyOnWriteArrayList对象。它是通过CopyOnWriteArrayList实现的。

map集合:

ConcurrentHashMap是线程安全的哈希表(相当于线程安全的HashMap);

ConcurrentSkipListMap是线程安全的有序的ConcurrentSkipListMap是线程安全的有序的哈希表(相当于线程安全的TreeMap);
   它继承于AbstactMap类,并且实现ConcurrentNavigableMap接口。
   ConcurrentSkipListMap是通过“跳表”来实现的,它支持并发;哈希表(相当于线程安全的TreeMap);

   ConcurrentSkipListSet是线程安全的有序的集合(相当于线程安全的TreeSet);它继承于AbstractSet,并实现了NavigableSet接口。

 Queue队列:
      ➣ ArrayBlockingQueue是数组实现的线程安全的有界的阻塞队列;
      ➣ LinkedBlockingQueue是单向链表实现的(指定大小)阻塞队列,该队列按FIFO(先进先出)排序元素;
      ➣ LinkedBlockingDeque是双向链表实现的(指定大小)双向并发阻塞队列,
         该阻塞队列同时支持FIFO和FILO两种操作方式;
      ➣ ConcurrentLinkedQueue是单向链表实现的无界队列,该队列按FIFO(先进先出)排序元素。
      ➣ ConcurrentLinkedDeque是双向链表实现的无界队列,该队列同时支持FIFO和FILO两种操作方式。

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class Demo6 {
    public static void main(String[] args) {
        List<String> all = new CopyOnWriteArrayList<String>();
        for (int i = 0; i < 20; i++) {
            int temp = i;
            new Thread(() -> {
                for (int j = 0; j < 30; j++) {
                    all.add(Thread.currentThread().getName() + "-" + temp + "-" + j);
                    System.out.println(all);
                }
            }).start();
        }
    }
}

ConcurrentHashMap的使用(代码没什么变化)

Map集合的主要特征是做数据的查询处理操作,所以在ConcurrentHashMap设计的时候考虑到了数据更新的安全性与数据查询的并发性。
JDK1.7之前
ConcurrentHashMap采用锁分段机制,默认并发级别为16。
特点是写的时候同步写入,使用独占锁,读的时候为了保证性能使用了共享锁。
JDK1.8以后
ConcurrentHashMap写的时候采用CAS无锁算法进一步提高写入效率。

ArrayBlockingQueue 是数组实现线程安全的有界的阻塞队列,可以作为线程通信同步工具类的使用。

六.同步工具类 CountDownLatch(倒计时) CyclicBarrier(同一个起跑线)  Semaphore

1.CountDownLatch类是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活动直到其他活动都完成才能继续执行:

(1)确保某个计算在其需要的所有资源都被初始化后才能继续执行。
    (2)确保某个服务在其依赖的所有其他服务都已经启动之后才启动。
    (3)等待直到某个操作所有参与者都执行完毕其他线程才能继续执行。

等子线程运行完 主线程再开始这类的问题。

2. CyclicBarrier 等待所有的线程都到位了再一起运行。

CyclicBarrier与CountDownLatch的区别

a.CountDownLatch只能用一次,CyclicBarrier可以reset,可以处理更加复杂的业务

b.CyclicBarrier有getNumberWaiting获取当前阻塞的线程数量,isbroken 判断阻塞的线程是否被中断。

3.Semaphore信号量 控制线程的并发数量 

用来控制同时访问特定资源的线程数量,通过协调保证合理的使用公共资源。

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值