多线程进阶=;JUC编程

Posted lsys

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程进阶=;JUC编程相关的知识,希望对你有一定的参考价值。

多线程进阶-->JUC并发编程

1.什么是JUC

源码+官方文档

java.util工具包,包,分类

业务:普通的线程代码 Thread

Runnable没有返回值,效率相比Callable相对较低

2.线程和进程

线程,进程,如果不能使用一句话说出来的技术,不扎实

进程:一个程序,QQ.exe Music.exe程序的集合;

一个进程可以包含多个线程,至少包含一个

Java默认有几个线程?2个 main ,GC

线程:开了一个进程Typora,写字自动保存(线程负责的)

对于java而言:Thread,Runnable,Callable

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++,Java无法直接操作硬件
private native void start0();

 

并发,并行

并发编程:并发,并行

并发(多线程同时操作同一资源)

。CPU一核,模拟出来多条线程,天下武功,为快不破,快速交替

并行(多个人一起行走)

。CPU多核,多个线程可以同时执行;

package com.yu.demo01;

public class Test1 {
   public static void main(String[] args) {
       //获取cpu的核数
       //cpu密集型,IO密集型
       System.out.println(Runtime.getRuntime().availableProcessors());
  }
}

并发编程的本质:充分利用CPU的资源

所有公司都很看重

企业,挣钱-->提高效率,裁员,找一个厉害的人顶替三个不怎么样的人

人员(减) 技术成本(高)

 

线程有几个状态

public enum State {
       //新生
       NEW,

       //运行
       RUNNABLE,

      //阻塞
       BLOCKED,

     //等待 死死的等
       WAITING,

       //超时等待
       TIMED_WAITING,

       //终止
       TERMINATED;
  }

 

wait/sleep 区别

1.来自不同的类

wait-->Object

sleep-->Thread

2.关于所锁的释放

wait会释放锁,sleep睡觉了,抱着锁睡觉的,不会释放

3.使用的范围是不同的

wait必须在同步代码块中

sleep可以在任何地方睡

4.是否需要捕获异常

wait不需要捕获异常

sleep必须要捕获异常

3.Lock锁(重点)

传统的synchronized

package com.yu.demo01;
/*
* 真正的多线程并发公司中的并发,降低耦合性
* 线程就是一个单独的一个资源类,没有任何附属的操作
* 1.属性 方法
* */
public class SaleTicketDemo01 {
   public static void main(String[] args) {
   //并发:多线程操作同一资源类。把资源类丢入线程
       Ticket ticket = new Ticket();

       //@FunctionalInterface 函数式接口 jdk1.8   lambda表达式(参数)->{代码}
       new Thread(()->{
           for (int i = 0; i < 40; i++) {
               ticket.sale();
          }
      },"A").start();
       new Thread(()->{
           for (int i = 0; i < 40; i++) {
               ticket.sale();
          }
      },"B").start();
       new Thread(()->{
           for (int i = 0; i < 40; i++) {
               ticket.sale();
          }
      },"C").start();
  }
}
//资源类
class Ticket{
   //属性 方方法
   private  int number = 30;

   //买票的方式
   //synchronized 本质:队列,锁
   public synchronized void  sale(){
       if (number>0){
           System.out.println(Thread.currentThread().getName() + "卖出了" + (number--) + "票,剩余:"+number);
      }
  }
   //对象 class
}

 

Lock接口

公平锁:十分公平,可以先来后到

非公平锁:十分不公平:可以插队(默认

package com.yu.demo01;

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

public class SaleTicketDemo02 {
   public static void main(String[] args) {
       //并发:多线程操作同一资源类。把资源类丢入线程
       Ticket2 ticket = new Ticket2();

       //@FunctionalInterface 函数式接口 jdk1.8   lambda表达式(参数)->{代码}
       new Thread(()->{ for (int i = 0; i < 40; i++) ticket.sale(); },"A").start();
       new Thread(()->{ for (int i = 0; i < 40; i++) ticket.sale(); },"B").start();
       new Thread(()->{ for (int i = 0; i < 40; i++) ticket.sale(); },"C").start();

  }
}
   //lock三部曲
   //1. new ReentrantLock();
   //2.lock.lock();//加锁
   //3. finally--> lock.unlock(); //解锁
   class Ticket2 {
       //属性 方法
       private int number = 30;
       Lock lock =  new ReentrantLock();
       //买票的方式
       public void sale() {
           lock.lock();//加锁
           try {
               //业务代码
               if (number > 0) {
                   System.out.println(Thread.currentThread().getName() + "卖出了" + (number--) + "票,剩余:" + number);
              }
          } catch (Exception e) {
               e.printStackTrace();
          } finally {
               lock.unlock(); //解锁
          }
      }
       //锁的是 对象 class
  }

Synchronized和Lock区别

1.Synchronized 内置的java关键字,Lock是一个java类

2.Synchronized 无法判断获取锁的状态,Lock可以判断获取到了锁的状态

3.Synchronized 会自动释放锁,Lock必须要手动释放锁!如果不释放,死锁

4.Synchronized 线程1(获得锁,阻塞),线程2(等待,傻傻的等),Lock就不一定会等待下去

5.Synchronized 可重入锁,不可以中断的,非公平;Lock 可重入锁,可以判断锁,非公平(可以自己设置)

6.Synchronized 适合锁锁少量的代码同步问题,Lock适合锁大量的同步代码

锁是什么,如何判断锁的是谁

4.生产者和消费者问题

面试:单例模式,排序算法,生产者和消费者问题,死锁

生产者和消费者问题 Synchronized版

package com.yu.pc;
/*
* 线程之间的通信问题,生产者和消费者问题! 等待唤醒,通知唤醒
* 线程交替执行 A B 操作同一变量 num = 0
* A num+1
* B num-1
* */
public class A {
   public static void main(String[] args) {
       Data data = new Data();

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

       new Thread(()->{
           for (int i = 0; i < 10; i++) {
               try {
                   data.decrement();
              } catch (InterruptedException e) {
                   e.printStackTrace();
              }
          }
      },"B").start();
  }
}
//判断等待,业务,通知
class Data{//数字 资源类
   private int number = 0;

   //+1
   public synchronized void increment() throws InterruptedException {
       if (number != 0){//0
           //等待
           this.wait();
      }
       number++;
       System.out.println(Thread.currentThread().getName()+"=>"+number);
       //通知其他线程,我+1完毕了
       this.notifyAll();
  }

   //-1
   public synchronized void decrement() throws InterruptedException {
       if (number == 0){//1
           //等待
           this.wait();
      }
       number--;
       System.out.println(Thread.currentThread().getName()+"=>"+number);
       //通知其他线程,我-1完毕了
       this.notifyAll();
  }
}

问题存在 A B C D四个线程!虚假唤醒

if 改成 while判断

package com.yu.pc;
/*
* 线程之间的通信问题,生产者和消费者问题! 等待唤醒,通知唤醒
* 线程交替执行 A B 操作同一变量 num = 0
* A num+1
* B num-1
* */
public class A {
   public static void main(String[] args) {
       Data data = new Data();

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

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

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

       new Thread(()->{
           for (int i = 0; i < 10; i++) {
               try {
                   data.decrement();
              } catch (InterruptedException e) {
                   e.printStackTrace();
              }
          }
      },"D").start();
  }
}
//判断等待,业务,通知
class Data{//数字 资源类
   private int number = 0;

   //+1
   public synchronized void increment() throws InterruptedException {
       while (number != 0){//0
           //等待
           this.wait();
      }
       number++;
       System.out.println(Thread.currentThread().getName()+"=>"+number);
       //通知其他线程,我+1完毕了
       this.notifyAll();
  }

   //-1
   public synchronized void decrement() throws InterruptedException {
       while (number == 0){//1
           //等待
           this.wait();
      }
       number--;
       System.out.println(Thread.currentThread().getName()+"=>"+number);
       //通知其他线程,我-1完毕了
       this.notifyAll();
  }
}

JUC版的生产者和消费者问题

![(E:\\kuangshnegspeakjava\\image\\屏幕截图 2021-05-23 165358.png)

代码实现

package com.yu.pc;

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

public class B {
   public static void main(String[] args) {
       Data2 data = new Data2();

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

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

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

       new Thread(()->{
           for (int i = 0; i < 10; i++) {
               try {
                   data.decrement();
              } catch (InterruptedException e) {
                   e.printStackTrace();
              }
          }
      },"D").start();
  }
}
   //判断等待,业务,通知
   class Data2 {//数字 资源类
       private int number = 0;

       Lock lock = new ReentrantLock();
       Condition condition = lock.newCondition();
       //condition.await();//等待
       //condition.signalAll();//唤醒全部
       //+1
       public  void increment() {
           lock.lock();
           try {
               while (number != 0) {//0
                   //等待
                   condition.await();
              }
               number++;
               System.out.println(Thread.currentThread().getName() + "=>" + number);
               //通知其他线程,我+1完毕了
               condition.signalAll();
          }catch (Exception e){
               e.printStackTrace();
          }finally {
               lock.unlock();
          }
      }

       //-1
       public  void decrement() throws InterruptedException {
           lock.lock();
           try {
               while (number == 0) {//1
                   //等待
                   condition.await();
              }
               number--;
               System.out.println(Thread.currentThread().getName() + "=>" + number);
               //通知其他线程,我-1完毕了
               condition.signalAll();
          }catch (Exception e){
               e.printStackTrace();
          }finally {
               lock.unlock();
          }

      }
  }

任何一个新的技术,绝对不是仅仅只是覆盖了原来的技术,优势和补充

Condition 精准的通知和唤醒线程

 

以上是关于多线程进阶=;JUC编程的主要内容,如果未能解决你的问题,请参考以下文章

JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段

多线程进阶(JUC-1)准备知识

java多线程进阶JUC工具集

java多线程进阶JUC工具集

java进阶—JUC编程

JUC并发编程 线程运行原理 -- 多线程 & 上下文切换