JUC并发学习笔记

JUC并发编程

学习记录狂神视频JUC

1.获取线程数

/**
 * @author :程序员徐大大
 * @description:TODO
 * @date :2022-04-18 22:03
 */
public class Test01 {
    public static void main(String[] args) {
        //获取cpu的核数
        //cpu 密集型 ,io密集型
        System.out.println(Runtime.getRuntime().availableProcessors());

    }
}

  • 进程:一个程序,QQ.exe Music.exe 程序的集合; 一个进程往往可以包含多个线程,至少包含一个!

  • Java默认有几个线程? 2 个 mian、

  • GC 线程:开了一个进程

  • 对于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();

1. 并发编程

  1. 并发、并行 并发(多线程操作同一个资源) CPU 一核 ,模拟出来多条线程,快速交替

  2. 并行(多个人一起行走) CPU 多核 ,多个线程可以同时执行;

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

线程有几个状态

public enum State {
// 新生
NEW,
// 运行
RUNNABLE,
// 阻塞
BLOCKED,
// 等待,死死地等
WAITING,
// 超时等待
TIMED_WAITING,
// 终止
TERMINATED;
}

wait/sleep 区别

1、来自不同的类 wait => Object sleep => Thread

2、关于锁的释放 wait 会释放锁,sleep 睡觉了,抱着锁睡觉,不会释放!

3、使用的范围是不同的 wait ->wait必须在同步

4、是否需要捕获异常 wait 不需要捕获异常 sleep 必须要捕获异常

Locke锁

1.传统加锁方式synchronized

package com.xuda.lock;

/**
 * @author :程序员徐大大
 * @description:买票
 * @date :2022-04-18 22:08
 */

/**
 * 真正的多线程开发,
 * 线程就是一个单独的资源类,没有任何附属的操作
 * 1.属性 2.方法
 */
public class Test02 {
    public static void main(String[] args) {
        //并发:多线程操作同一个资源,吧资源丢入线程
        Ticket ticket = new Ticket();
        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();
    }
}
    //资源类 oop
    class Ticket {
        //属性 、方法
        private int number = 30;
        //买票方法
        // synchronized 本质: 队列,锁
        public synchronized void sale() {
            if (number > 0) {
                System.out.println(Thread.currentThread().getName()+"卖出了"+(number--)+"票,剩余:"+number);

            }
        }
}

2.ReenteantLock锁

Lock三部曲

(1).new ReentrantLock();

(2).lock.lock(); // 加锁

(3).finally=>lock.unlock(); //解锁

package com.xuda.lock;

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

/**
 * @author :程序员徐大大
 * @description:Lock锁
 * @date :2022-04-19 17:39
 */
  //ReentrantLock :可重用锁
    // ReentrantReadWriteLock.ReadLock :读锁
    // ReentrantReadWriteLock.WriteLock :写锁

/**公平锁
 *  public ReentrantLock() {
 *         sync = new NonfairSync();
 *     }
 *非公平锁
 *       public ReentrantLock(boolean fair){
 *          sync=fair?new FairSync():new NonfairSync();
 *          }
 */
public class SaleTicketDemo02 {
    //公平锁:十分公平:可以先来后到
    //非公平锁:十分不公平:可以插队 (默认)
    public static void main(String[] args) {
        //并发:多线程操作同一个资源类,吧资源丢入线程
        Ticket2 ticket2 = new Ticket2();
        // @FunctionalInterface 函数式接口,jdk1.8 lambda表达式 (参数)->{ 代码 }
        new Thread(()->{
            for (int i = 0; i < 40; i++) {
                ticket2.sale();
            }
        },"A").start();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                ticket2.sale();
            }
        },"B").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                ticket2.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(); //解锁
           }
       }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C3078dmr-1650373232105)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650363597951.png)]

1、Synchronized 内置的Java关键字, Lock 是一个Java类

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

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

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

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

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

生产者和消费者

:单例模式、排序算法、生产者和消费者、死锁

生产者和消费者问题 Synchronized 版

package com.xuda.lock;

/**
 * @author :程序员徐大大
 * @description:TODO
 * @date :2022-04-19 18:22
 */
public class dieLock {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();
    }
}
//判断等待、业务、通知
class Data { //资源
    private int number = 0;

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


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MFSwwS1G-1650373232105)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650365800713.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B8Y0wTdL-1650373232106)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650366234829.png)]

上面会产生虚假唤醒

if 改为 while 判断

package com.xuda.lock;

/**
 * @author :程序员徐大大
 * @description:TODO
 * @date :2022-04-19 18:22
 */
public class dieLock {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();

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

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

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


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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CGlnattL-1650373232106)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650368535008.png)]

通过Lock 找到 Condition

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eGYBA7q9-1650373232107)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650366522152.png)]

package com.xuda.lock;

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

/**
 * @author :程序员徐大大
 * @description:TODO
 * @date :2022-04-19 19:17
 */
public class LockIn {
    public static void main(String[] args) {
        Data2 data2 = new Data2();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data2.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data2.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data2.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"C").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data2.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(); // 唤醒全部
    public  void increment() throws InterruptedException {
        lock.lock(); //加锁
        try {
            while (number != 0) {
                //等待
                condition.await();
            }
            number++;
            System.out.println(Thread.currentThread().getName() + "==>" + number);
            // 通知其他线程,我+1完成了
            condition.signalAll(); //唤醒其他所有线程
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();//解锁
        }
    }
    public  void decrement() throws InterruptedException {
        lock.lock(); //加锁
        try {
            while (number == 0) {
                //等待
                condition.await();
            }
            number--;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            //通知其他线程,我-1完毕
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CUQ3JfJv-1650373232107)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650368447724.png)]

狂神:任何一个的新技术,绝对不是仅仅只是覆盖了原来的技术

优势和补充 Condition精准的通知和唤醒

package com.xuda.lock;

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

/**
 * @author :程序员徐大大
 * @description:TODO
 * @date :2022-04-19 19:17
 */
public class LockIn {
    /**
     * A 执行完调用B,B执行完调用C,C执行完调用A
     */

    public static void main(String[] args) {
        Data2 data2 = new Data2();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                data2.printA();
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                data2.printB();
            }
        },"B").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                data2.printC();
            }
        },"C").start();
    }
}
//判断等待、业务、通知
    class Data2{
    private Lock lock = new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();
    private int number = 1; // 1A 2B 3C
public void printA(){
    lock.lock();
    try {
// 业务,判断-> 执行-> 通知
        while (number!=1){
// 等待
            condition1.await();
        }
        System.out.println(Thread.currentThread().getName()+"=>AAAAAAA");
// 唤醒,唤醒指定的人,B
        number = 2;
        condition2.signal();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}
    public void printB(){
        lock.lock();
        try {
// 业务,判断-> 执行-> 通知
            while (number!=2){
                condition2.await();
            }
            System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBB");
// 唤醒,唤醒指定的人,c
            number = 3;
            condition3.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void printC(){
        lock.lock();
        try {
// 业务,判断-> 执行-> 通知
// 业务,判断-> 执行-> 通知
            while (number!=3){
                condition3.await();
            }
            System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBB");
// 唤醒,唤醒指定的人,c
            number = 1;
            condition1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-II32tcef-1650373232108)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650369273699.png)]

八锁现象

如何判断锁的是谁!永远的知道什么锁,锁到底锁的是谁!

深刻理解我们的锁

8锁,就是关于锁的8个问题 *

1.synchronized的锁
package com.xuda.eitlock;

import java.util.concurrent.TimeUnit;

/**
 * @author :程序员徐大大
 * @description:TODO
 * @date :2022-04-19 20:15
 */
public class CallTest {
    /**
     * 8锁,就是关于锁的8个问题
     * 1、标准情况下,两个线程先打印 发短信还是 打电话? 1/发短信 2/打电话
     * 1、sendSms延迟4秒,两个线程先打印 发短信还是 打电话? 1/发短信 2/打电话
     */
    public static void main(String[] args) {
        Phone phone1 = new Phone();
        //锁的存在
        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        new Thread(()->{
            phone1.call();
        },"A").start();
    }

}
class Phone {
    // synchronized 锁的对象是方法的调用者
    //两个方法用的是同一个锁,谁先拿到谁先执行
    public synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public synchronized void call() {
        System.out.println("打电话");
    }
}


synchronized锁的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cDS4mdfd-1650373232108)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650371178566.png)]

2.synchronized锁的是方法不是类

package com.xuda.eitlock;

import java.util.concurrent.TimeUnit;

/**
 * @author :程序员徐大大
 * @description:TODO
 * @date :2022-04-19 20:28
 */
public class CallTest2 {
    public static void main(String[] args) {
        Phone2 phone2 = new Phone2();
        //锁的存在
        new Thread(()->{
            phone2.sendSms();
        },"A").start();
        new Thread(()->{
            phone2.call();
        },"A").start();
        new Thread(()->{
            phone2.hello();
        },"A").start();
    }

}
class Phone2 {
    // synchronized 锁的对象是方法的调用者
    //两个方法用的是同一个锁,谁先拿到谁先执行
    public synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public synchronized void call() {
        System.out.println("打电话");
    }
    public  void hello() {
        System.out.println("hello");
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qa0gAfN5-1650373232108)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650371519478.png)]

2.加入static后static 静态方法类一加载就有了!所以synchronized锁的是Class

package com.xuda.eitlock;

import java.util.concurrent.TimeUnit;

/**
 * @author :程序员徐大大
 * @description:TODO
 * @date :2022-04-19 20:32
 */
public class CallTest3 {
    public static void main(String[] args) {
    // 两个对象的Class类模板只有一个,static,锁的是Class
        Phone3 phone1 = new Phone3();
        Phone3 phone2 = new Phone3();
        //锁的存在
        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        // 捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}

class Phone3{
// synchronized 锁的对象是方法的调用者!
// static 静态方法
// 类一加载就有了!锁的是Class
public static synchronized void sendSms(){
    try {
        TimeUnit.SECONDS.sleep(4);
    } catch (InterruptedException e) {
         e.printStackTrace();
        }
         System.out.println("发短信");
    }
public static synchronized void call(){
        System.out.println("打电话");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ivfJo0b6-1650373232109)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650371670952.png)]

3.静态的同步方法 锁的是 Class 类模板,普通的同步方法 锁的调用者

package com.xuda.eitlock;

import java.util.concurrent.TimeUnit;

/**
 * @author :程序员徐大大
 * @description:TODO
 * @date :2022-04-19 20:32
 */
public class CallTest3 {
    public static void main(String[] args) {
    // 两个对象的Class类模板只有一个,static,锁的是Class
        Phone3 phone1 = new Phone3();
        Phone3 phone2 = new Phone3();
        //锁的存在
        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        // 捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}

class Phone3{
    // 静态的同步方法 锁的是 Class 类模板
    public static synchronized void sendSms(){
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    // 普通的同步方法 锁的调用者
    public synchronized void call(){
        System.out.println("打电话");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qqbfAmz9-1650373232109)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650371798885.png)]

new this 具体的一个实体类

static Class 唯一的一个模板

集合类不安全

1.List不安全使用CopyOnWriteArrayList

package com.xuda.list;

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

/**
 * @author :程序员徐大大
 * @description:TODO
 * @date :2022-04-19 20:42
 */
// java.util.ConcurrentModificationException 并发修改异常!

public class ListTest {

    public static void main(String[] args) {
        //并发下 ArrayList不安全
        /**
         * 解决方案;
         * 1、List<String> list = new Vector<>();
         * 2、List<String> list = Collections.synchronizedList(new ArrayList<>
         ());
         * 3、List<String> list = new CopyOnWriteArrayList<>();
         */
    // CopyOnWrite 写入时复制 COW 计算机程序设计领域的一种优化策略;
    // 多个线程调用的时候,list,读取的时候,固定的,写入(覆盖)
    // 在写入的时候避免覆盖,造成数据问题!
    // 读写分离
    // CopyOnWriteArrayList 比 Vector 厉害在哪里?
        List<String> list = new CopyOnWriteArrayList<>();
    for (int i = 1; i <= 10; i++) {
        new Thread(()->{
            list.add(UUID.randomUUID().toString().substring(0,5));
            System.out.println(list);
        }).start();
    }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WW7Lw3k8-1650373232110)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650372359869.png)]

2.Set不安全,使用CopyOnWriteArraySet

package com.xuda.list;

/**
 * @author :程序员徐大大
 * @description:Set不安全
 * @date :2022-04-19 20:46
 */


import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 同理可证 : ConcurrentModificationException
 * //1、Set<String> set = Collections.synchronizedSet(new HashSet<>());、
 */
public class Set {
    // Set<String> set = new HashSet<>();
// Set<String> set = Collections.synchronizedSet(new HashSet<>());
    public static void main(String[] args) {
        CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();
        for (int i = 0; i < 30; i++) {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(set);
            }).start();
        }
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vWPhbYg9-1650373232110)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650372780812.png)]

  1. hashSet 底层是什么?
public HashSet() {
map = new HashMap<>();
}
// add set 本质就是 map key是无法重复的!
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
private static final Object PRESENT = new Object(); // 不变得值!

  1. Map 不安全
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
	// ConcurrentModificationException
public class MapTest {
    public static void main(String[] args) {
	// map 是这样用的吗? 不是,工作中不用 HashMap
	// 默认等价于什么? new HashMap<>(16,0.75);
	// Map<String, String> map = new HashMap<>();
	// 唯一的一个家庭作业:研究ConcurrentHashMap的原理
	Map<String, String> map = new ConcurrentHashMap<>();
	for (int i = 1; i <=30; i++) {
		new Thread(()->{
map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().subst			ring(
		0,5));
		System.out.println(map);
			},String.valueOf(i)).start();
		}
	}
}

5.Callable

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O6jv7ubK-1650373232111)(C:\Users\86176\AppData\Roaming\Typora\typora-user-images\1650373110873.png)]

1、可以有返回值

2、可以抛出异常

3、方法不同,run()/ call()

在这里插入图片描述

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.locks.ReentrantLock;
/**
* 1、探究原理
* 2、觉自己会用
*/
public class CallableTest {
public static void main(String[] args) throws ExecutionException,
InterruptedException {
// new Thread(new Runnable()).start();
// new Thread(new FutureTask<V>()).start();
// new Thread(new FutureTask<V>( Callable )).start();
	new Thread().start(); // 怎么启动Callable
	MyThread thread = new MyThread();
	FutureTask futureTask = new FutureTask(thread); // 适配类
	new Thread(futureTask,"A").start();
	new Thread(futureTask,"B").start(); // 结果会被缓存,效率高
Integer o = (Integer) futureTask.get(); //这个get 方法可能会产生阻塞!把他放到
//最后
	// 或者使用异步通信来处理!	
	System.out.println(o);
	}
}
class MyThread implements Callable<Integer> {
@Override
public Integer call() {
	System.out.println("call()"); // 会打印几个call
		// 耗时的操作
	return 1024;
}

细节: 1、有缓存 2、结果可能需要等待,会阻塞!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小徐同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值