JUC整理(一)

什么是JUC

java.util .concurrent 工具包

线程和进程

  • 进程 :运行起来的程序
    • 一个进程最少包含一个线程
  • 线程: java默认有几个线程 2个 main 和GC

Java真的能够开启一个线程吗?

  • 是不能的 他是调用的本地的方法去开启一个线程
  public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }
		//调用底层c++  来操作硬件
    private native void start0();

并发和并行区别

  • 并发才会有多线程
    • 单核CPU通过快速交替模拟并发
  • 并行 多人一起行走
    • 多核CPU可以实现并行
 public static void main(String[] args) {
        //获取CPU的核数  返回的是可用的计算资源
        System.out.println(Runtime.getRuntime().availableProcessors());
    }

线程的六种状态

 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:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * 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:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
     //超时等待
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
     //死亡 终止
        TERMINATED;
    }

wait/sleep 区别

  • 来自不同的类
    • wait =>Object
    • sleep=> Thread
  • 锁的释放
    • wait会释放锁,sleep睡觉 不会释放
  • 使用范围不同
    • wait 在同步的代码块当中
    • sleep 可以在任何地方加
  • 是否需要捕获异常
    • wait 需要中断异常
    • sleep需要捕获异常

Lock锁

  • synchronized 本质为排队 同步

    • public class LockDemo {
          public static void main(String[] args) {
              Monney monney = new Monney();
              new Thread(()->{
                  for (int i = 0; i < 70; i++) {
                      monney.quqian();
                  }
              },"a").start();
              new Thread(()->{
                  for (int i = 0; i < 70; i++) {
                      monney.quqian();
                  }
              },"b").start();
          }
      }
      class Monney{
          int num = 100;
         // Lock lock = new ReentrantLock();
          public synchronized void quqian(){
           //   lock.lock();
              if(num>0) {
                  System.out.println(Thread.currentThread().getName() + num-- + "取钱成功");
              }
             // lock.unlock();
          }
      }
      
      
  • Lock

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oCML3CjB-1646231988370)(D:\桌面\截图\image-20220221143707889.png)]

public class LockDemo {
    public static void main(String[] args) {
        Monney monney = new Monney();
        new Thread(()->{
            for (int i = 0; i < 70; i++) {
                monney.quqian();
            }
        },"a").start();
        new Thread(()->{
            for (int i = 0; i < 70; i++) {
                monney.quqian();
            }
        },"b").start();
    }
}
class Monney{
    int num = 100;
    Lock lock = new ReentrantLock();
    public  void quqian(){
       lock.lock();
        if(num>0) {
            System.out.println(Thread.currentThread().getName() + num-- + "取钱成功");
        }
        lock.unlock();
    }
}

synchronized 和Lock 区别

  • synchronized 是内置的java关键字,Lock是一个java接口
  • synchronized 无法判断获取锁的状态,Lock可以判断是否获取到了锁
  • synchronized 会自动释放锁,lock必须要手动释放锁!如果不是释放就会死锁
  • synchronized 线程1(获得锁并且阻塞) 线程2 会一直等待下去; 二Lock锁不会一直等待下去 lock.tryLock() 方法会去尝试获取锁
  • synchronized 可重入锁,不可中断的,非公平;Lock,可重入锁,可以 判断锁,非公平(可以自己设置)
  • synchronized适合锁少量的代码同步问题, Lock适合锁大量的代码

公平锁和非公平锁

  • 公平锁: 十分公平,先来后到
  • 非公平锁:

Condition

  • Condition可以精准的通知和唤醒线程 不再是线程去争抢CPU
public class ConditionDemo {
    private Lock lock = new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();
    private int number = 1;  // 1唤醒A  2唤醒B  3唤醒C

    public void printA(){
        lock.lock();
        try {
            while(number!=1){
                condition1.await();
            }
            System.out.println("AAAAAAAAA");
            condition2.signal();
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void printB(){
        lock.lock();
        try {
            while(number!=2){
                condition2.await();
            }
            System.out.println("BBBBBBBBB");
            condition3.signal();
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void printC(){
        lock.lock();
        try {
            while(number!=1){
                condition3.await();
            }
            System.out.println("CCCCCCC");
            condition1.signal();
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

  1. synchronized 锁的对象是方法的调用者
  2. synchronized 如果加了static 锁的就是编译过的.class模板

List如何保证安全

以下方法会报错

java.util.ConcurrentModificationException 并发修改异常错误

  public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        for(int i =0;i<10;i++){
            new Thread(()->{
              list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(list);
            }).start();
        }

    }

用concurrent包下的实现可以避免异常

  • 原理: CopyOnWrite写入时复制 计算机程序设计领域的优化策略
  • 在写入的时候避免覆盖,造成数据问题
public static void main(String[] args) {
        List<String> list = new CopyOnWriteArrayList<>();
        for(int i =0;i<10;i++){
            new Thread(()->{
              list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(list);
            }).start();
        }
    }

同理可得 CopyOnWriteArraySet<>();

map线程安全的两种实现方式 多线程下 实际开发当中经常使用

//1
HashMap<String,String> map = new HashMap<>();
        Collections.synchronizedMap(map);
//2 
 Map<String,String> map = new ConcurrentHashMap<>();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值