• 33-Java多线程


    33-Java多线程-qianfeng-笔记



    一、什么是多线程

    ①:什么是进程

    在这里插入图片描述

    ②:什么是线程

    在这里插入图片描述

    ③:进程与线程的区别

    在这里插入图片描述

    二、线程的组成

    ①:组成

    在这里插入图片描述

    ②:线程的特点

    在这里插入图片描述

    ③:创建线程的三种方式

    在这里插入图片描述

    01.【继承Thread类,重写run方法】

    1. 代码实现

    package com.example.d6_thread;
    
    public class MyThread extends Thread{
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.println("子线程..........." + i);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    package com.example.d6_thread;
    
    public class TestThread {
        public static void main(String[] args) {
            // 1.创建线程对象
            MyThread myThread = new MyThread();
            // 2.启动线程
            myThread.start();
            // 3.主线程执行
            for (int i = 0; i < 100; i++) {
                System.out.println("主线程=======================" + i);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    2.获取线程名称和Id

    在这里插入图片描述

    方式一:
    在这里插入图片描述在这里插入图片描述
    方式二:
    在这里插入图片描述在这里插入图片描述

    3.修改线程的名称

    方式一:
    在这里插入图片描述在这里插入图片描述
    方式二:
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

    4. 窗口买票案例

    在这里插入图片描述

    package com.example.d6_thread;
    
    public class TicketWin extends Thread{
        private int ticketCount = 100;
        public TicketWin() {
        }
    
        public TicketWin(String name) {
            super(name);
        }
    
        @Override
        public void run() {
            while (ticketCount > 0){
                System.out.println(Thread.currentThread().getName()+" 卖出了第 " + (101-ticketCount) + "张票~~~~");
                ticketCount--;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    package com.example.d6_thread;
    
    public class TestTicket {
        public static void main(String[] args) {
            TicketWin ticketWin = new TicketWin("窗口1");
            TicketWin ticketWin2 = new TicketWin("窗口2");
            TicketWin ticketWin3 = new TicketWin("窗口3");
            TicketWin ticketWin4 = new TicketWin("窗口4");
            ticketWin.start();
            ticketWin2.start();
            ticketWin3.start();
            ticketWin4.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    02.【实现Runnable接口】

    1.代码实现

    方式一:

    package com.example.d6_thread;
    
    public class MyRunnable implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.println("线程名称:" + Thread.currentThread().getName() + i);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    package com.example.d6_thread;
    
    public class TestRunnable {
        public static void main(String[] args){
            MyRunnable myRunnable = new MyRunnable();
            Thread thread = new Thread(myRunnable,"我的线程");
            thread.start();
            for (int i = 0; i < 100; i++) {
                System.out.println("main...................." + i);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    方式二:使用匿名内部类实现

    package com.example.d6_thread;
    
    public class TestRunnable {
        public static void main(String[] args){
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 100; i++) {
                        System.out.println("线程名称:" + Thread.currentThread().getName() + i);
                    }
                }
            };
            // 创建线程对象
            Thread thread = new Thread(runnable,"我的线程1  ");
            thread.start();
            for (int i = 0; i < 100; i++) {
                System.out.println("main...................." + i);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    2.Runnable案例1

    在这里插入图片描述

    package com.example.d7_runnableDemo;
    
    public class Ticket implements Runnable{
        private static int ticketNum = 100;
        @Override
        public void run() {
            while (ticketNum > 0){
                System.out.println("线程名称:" + Thread.currentThread().getName() + (101 - ticketNum));
                ticketNum --;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    package com.example.d7_runnableDemo;
    
    public class TestTicket {
        public static void main(String[] args) {
            Ticket ticket = new Ticket();
            Thread thread = new Thread(ticket,"窗口1 ");
            Thread thread2 = new Thread(ticket,"窗口2 ");
            Thread thread3 = new Thread(ticket,"窗口3 ");
            Thread thread4 = new Thread(ticket,"窗口4 ");
            thread.start();
            thread2.start();
            thread3.start();
            thread4.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    票数卖重的情况后面会解决
    在这里插入图片描述

    3.Runnable案例2

    在这里插入图片描述> 方式一:

    package com.example.d7_runnableDemo;
    
    public class BankCard {
        private int money;
    
        public int getMoney() {
            return money;
        }
    
        public void setMoney(int money) {
            this.money = money;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    package com.example.d7_runnableDemo;
    
    public class AddMoney implements Runnable{
        private BankCard bankCard;
    
        public AddMoney(BankCard bankCard) {
            this.bankCard = bankCard;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                bankCard.setMoney(bankCard.getMoney() + 1000);
                System.out.println(Thread.currentThread().getName() + "存了1000元"+ " 余额为:" +bankCard.getMoney()+"元~");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    package com.example.d7_runnableDemo;
    
    public class SubMoney implements Runnable{
        private BankCard bankCard;
    
        public SubMoney(BankCard bankCard) {
            this.bankCard = bankCard;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                if (bankCard.getMoney() >= 1000){
                    bankCard.setMoney(bankCard.getMoney() - 1000);
                    System.out.println(Thread.currentThread().getName() + "取了1000元"+ " 余额为:" +bankCard.getMoney()+"元!");
                }else {
                    System.out.println("余额不足,赶快存钱。。。。。");
                    i--;
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    package com.example.d7_runnableDemo;
    
    public class TestBankCard {
        public static void main(String[] args) {
            BankCard bankCard = new BankCard();
            AddMoney addMoney = new AddMoney(bankCard);
            SubMoney subMoney = new SubMoney(bankCard);
            Thread thread = new Thread(addMoney,"小黑 ");
            Thread thread1 = new Thread(subMoney, "小美 ");
            thread.start();
            thread1.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    方式二:匿名内部类实现方式

    package com.example.d7_runnableDemo;
    
    public class TestBankCard2 {
        public static void main(String[] args) {
            BankCard bankCard = new BankCard();
    
            Runnable add = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        bankCard.setMoney(bankCard.getMoney() + 1000);
                        System.out.println(Thread.currentThread().getName() + "存了1000元"+ " 余额为:" +bankCard.getMoney()+"元~");
                    }
                }
            };
    
            Runnable sub = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        if (bankCard.getMoney() >= 1000){
                            bankCard.setMoney(bankCard.getMoney() - 1000);
                            System.out.println(Thread.currentThread().getName() + "取了1000元"+ " 余额为:" +bankCard.getMoney()+"元!");
                        }else {
                            System.out.println("余额不足,赶快存钱。。。。。");
                            i--;
                        }
                    }
                }
            };
    
            new Thread(add,"小白 ").start();
            new Thread(sub,"小美 ").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    在这里插入图片描述

    03.实现Callable接口

    计算1-100的和

    1.用法一

    在这里插入代码片package com.example.d10_executor;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class CallableThread {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            // 创建一个Callable对象 完成1-100的和
            Callable<Integer> callable = new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    System.out.println(Thread.currentThread().getName() + "开始计算~");
                    int sum = 0;
                    for (int i = 0; i < 100; i++) {
                        sum += i;
                    }
                    return sum;
                }
            };
            // 将Callable 转换成可执行对象
            FutureTask<Integer> futureTask = new FutureTask<>(callable);
            // 创建线程并启动
            new Thread(futureTask).start();
            // 获取结果(等待Callable执行完毕)
            Integer integer = futureTask.get();
    
            System.out.println("结果是:" + integer);
    
    
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    在这里插入图片描述

    2.用法二 (结合线程池使用)

    package com.example.d10_executor;
    
    import java.util.concurrent.*;
    
    public class CallableThread2 {
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            // 1.创建线程池
            ExecutorService pool = Executors.newFixedThreadPool(1);
            // 2.提交任务
            Future<Integer> future = pool.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    int sum = 0;
                    System.out.println(Thread.currentThread().getName() + "开始计算~");
                    for (int i = 0; i < 100; i++) {
                        sum += i;
                    }
                    return sum;
                }
            });
            // 3.获取结果
            Integer integer = future.get();
            System.out.println("结果是:" + integer);
            // 4.关闭线程池
            pool.shutdown();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

    3.并发计算

    package com.example.d10_executor;
    
    import java.util.concurrent.*;
    
    public class CallableThread3 {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            // 1.创建一个线程池
            ExecutorService pool = Executors.newFixedThreadPool(2);
            // 2.1 创建任务1
            Future<Integer> future1 = pool.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    int sum1 = 0;
                    System.out.println(Thread.currentThread().getName() + "计算开始~");
                    for (int i = 0; i < 50; i++) {
                        sum1 += i;
                    }
                    return sum1;
                }
            });
            // 2.2 创建任务2
            Future<Integer> future2 = pool.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    int sum2 = 0;
                    System.out.println(Thread.currentThread().getName() + "计算开始~");
                    for (int i = 50; i < 100; i++) {
                        sum2 += i;
                    }
                    return sum2;
                }
            });
            // 3.获取结果
            Integer integer1 = future1.get();
            Integer integer2 = future2.get();
    
            System.out.println("结果是:" + (integer1 + integer2));
            // 4.关闭线程池
            pool.shutdown();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    在这里插入图片描述

    三、线程的状态

    在这里插入图片描述

    ①:休眠 (sleep)

    package com.example.d8_threadStatus;
    
    public class SleepThread implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println("线程名称: " + Thread.currentThread().getName() + ".........." + i);
                try {
                    Thread.sleep(1000); // sleep异常不也能直接抛出
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    package com.example.d8_threadStatus;
    
    public class TestSleep {
        public static void main(String[] args) {
            SleepThread s1 = new SleepThread();
            new Thread(s1).start();
    
            SleepThread s2 = new SleepThread();
            new Thread(s1).start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    ②:放弃 (yield)

    package com.example.d8_threadStatus;
    
    public class YieldThread implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println("线程名称:" + Thread.currentThread().getName() + ".........." + i);
                Thread.yield();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package com.example.d8_threadStatus;
    
    public class TestYield {
        public static void main(String[] args) {
            new Thread(new YieldThread()).start();
            new Thread(new YieldThread()).start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    ③:加入(join)

    package com.example.d8_threadStatus;
    
    public class JoinThread extends Thread{
        @Override
        public void run() {
            for (int i = 0; i < 50; i++) {
                System.out.println("线程名称: " + Thread.currentThread().getName() + ".........." + i);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    package com.example.d8_threadStatus;
    
    public class TestJoin {
        public static void main(String[] args) {
            JoinThread joinThread = new JoinThread();
            joinThread.start();
    
            for (int i = 0; i < 50; i++) {
                System.out.println("main........." + i);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    使用Join 加入线程的情况如下

    在这里插入图片描述

    ④:修改线程优先级(priority)

    在这里插入图片描述

    package com.example.d8_threadStatus;
    
    public class PriorityThread extends Thread{
        @Override
        public void run() {
            for (int i = 0; i < 50; i++) {
                System.out.println(Thread.currentThread().getName() + "=================="+i);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package com.example.d8_threadStatus;
    
    public class TestPriority {
        public static void main(String[] args) {
            // 创建线程
            PriorityThread p1 = new PriorityThread();
            p1.setName("p1");
            PriorityThread p3 = new PriorityThread();
            p3.setName("p3");
            // 设置优先级
            p1.setPriority(1);
            p3.setPriority(10);
            // 启动
            p1.start();
            p3.start();
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    ⑤:守护线程(Daemon)

    在这里插入图片描述

    package com.example.d8_threadStatus;
    
    public class DeamonThread extends Thread{
        @Override
        public void run() {
            for (int i = 0; i < 50; i++) {
                System.out.println(Thread.currentThread().getName() + "=========" + i);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    package com.example.d8_threadStatus;
    
    public class TestDeamon {
        public static void main(String[] args) {
            DeamonThread d1 = new DeamonThread();
            d1.setName("d1");
            d1.setDaemon(true);
            d1.start();
            for (int i = 0; i < 10; i++) {
                System.out.println("main............" + i);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    ⑥:线程状态(等待)

    在这里插入图片描述在这里插入图片描述在这里插入图片描述

    四、线程安全

    ①:线程安全问题

    在这里插入图片描述

    package com.example.d8_threadStatus;
    import java.util.Arrays;
    public class Test {
        private static int index = 0;
    
        public static void main(String[] args) throws InterruptedException {
            String[] s = new String[5];
            Runnable r1 = new Runnable() {
                @Override
                public void run() {
                    s[index] = "hello";
                    index++;
                }
            };
            Runnable r2 = new Runnable() {
                @Override
                public void run() {
                    s[index] = "word";
                    index++;
                }
            };
    
            Thread a = new Thread(r1, "r1");
            Thread b = new Thread(r2, "r2");
            a.start();
            b.start();
            // 加入线程保证a b 两个线程执行完
            a.join();
            b.join();
            System.out.println(Arrays.toString(s));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    在这里插入图片描述

    ②:同步代码块

    01.方式一:

    在这里插入图片描述
    在这里插入图片描述

    1.解决买票问题

    package com.example.d7_runnableDemo;
    
    public class Ticket implements Runnable{
        private static int ticketNum = 100;
        // 创建锁
        private Object object = new Object();
        @Override
        public void run() {
    
            while (true) {
                synchronized (object){
                    if (ticketNum <= 0){
                        break;
                    }
                    System.out.println("线程名称:" + Thread.currentThread().getName() + (101 - ticketNum));
                    ticketNum --;
                }
            }
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    package com.example.d7_runnableDemo;
    
    public class TestTicket {
        public static void main(String[] args) {
            Ticket ticket = new Ticket();
            Thread thread = new Thread(ticket,"窗口1 ");
            Thread thread2 = new Thread(ticket,"窗口2 ");
            Thread thread3 = new Thread(ticket,"窗口3 ");
            Thread thread4 = new Thread(ticket,"窗口4 ");
            thread.start();
            thread2.start();
            thread3.start();
            thread4.start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    2.解决存取钱问题

    package com.example.d7_runnableDemo;
    
    public class TestBankCard2 {
        public static void main(String[] args) {
            BankCard bankCard = new BankCard();
            // 存钱
            Runnable add = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        synchronized (bankCard){
                            bankCard.setMoney(bankCard.getMoney() + 1000);
                            System.out.println(Thread.currentThread().getName() + "存了1000元"+ " 余额为:" +bankCard.getMoney()+"元~");
                        }
                    }
                }
            };
            // 取钱
            Runnable sub = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        synchronized (bankCard){
                            if (bankCard.getMoney() >= 1000){
                                bankCard.setMoney(bankCard.getMoney() - 1000);
                                System.out.println(Thread.currentThread().getName() + "取了1000元"+ " 余额为:" +bankCard.getMoney()+"元!");
                            }else {
                                System.out.println("余额不足,赶快存钱。。。。。");
                                i--;
                            }
                        }
                    }
                }
            };
    
            new Thread(add,"小白 ").start();
            new Thread(sub,"小美 ").start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    在这里插入图片描述

    02. 方式二:(同步方法)

    在这里插入图片描述

    package com.example.d7_runnableDemo;
    
    public class Ticket implements Runnable{
        private static int ticketNum = 100;
        // 创建锁
        private Object object = new Object();
        @Override
        public void run() {
    
            while (true) {
                if (!tick()){
                    break;
                }
            }
        }
        public synchronized boolean tick(){
            if (ticketNum <= 0){
                return false;
            }
            System.out.println("线程名称:" + Thread.currentThread().getName() + (101 - ticketNum));
            ticketNum --;
            return true;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

    ③:同步规则

    在这里插入图片描述

    ④:死锁

    package com.example.d9_lock;
    
    public class MyLock {
        public static Object a = new Object();
        public static Object b = new Object();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    package com.example.d9_lock;
    
    public class TestLock {
        public static void main(String[] args) {
            Boy boy = new Boy();
            Girl girl = new Girl();
            boy.start();
            girl.start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package com.example.d9_lock;
    
    public class Boy extends Thread{
        @Override
        public void run() {
            synchronized (MyLock.a){
                System.out.println("男孩拿到了a");
                synchronized (MyLock.b){
                    System.out.println("男孩拿到了b");
                    System.out.println("可以开始吃了");
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    package com.example.d9_lock;
    
    public class Girl extends Thread{
        @Override
        public void run() {
            synchronized (MyLock.b){
                System.out.println("女孩拿到了b");
                synchronized (MyLock.a){
                    System.out.println("女孩拿到了a");
                    System.out.println("可以开始吃了");
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述
    在这里插入图片描述

    ⑤:线程通信

    在这里插入图片描述

    package com.example.d9_lock;
    
    public class AddAndSubMoney {
        public static boolean flag = false;
        public static  BankCard bankCard = new BankCard();
        private static AddAndSubMoney addAndSubMoney = new AddAndSubMoney();
        // 存钱
        public synchronized void sub1(){
            while (!flag){ // false 没有钱
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            bankCard.setMoney(bankCard.getMoney() - 1000);
            System.out.println(Thread.currentThread().getName() + "取了1000元,余额是"+bankCard.getMoney());
            // 修改标记
            flag = false;
            // 唤醒存钱线程
            this.notifyAll();
        }
        // 取钱
        public synchronized void save(){
            while (flag){ // true 有钱
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            bankCard.setMoney(bankCard.getMoney() + 1000);
            System.out.println(Thread.currentThread().getName() + "存了1000元,余额是"+bankCard.getMoney());
            // 修改标记
            flag = true;
            // 唤醒取钱线程
            this.notifyAll();
        }
    
        public static void main(String[] args) {
            Runnable add = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        addAndSubMoney.save();
                    }
                }
            };
            Runnable sub = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        addAndSubMoney.sub1();
                    }
                }
            };
            new Thread(sub,"小白").start();
            new Thread(add,"小黑").start();
            new Thread(sub,"小华").start();
            new Thread(add,"小明").start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    在这里插入图片描述

    经典问题(生产者 消费者)

    在这里插入图片描述

    package com.example.d9_lock;
    
    public class ProductionAndConsumeBread {
        private static ProductionAndConsumeBread p = new ProductionAndConsumeBread();
        // 存放面包的数组
        private static Bread[] breads = new Bread[6];
        // 存放面包的位置
        private static int index = 0;
        // 存放面包
        public  synchronized void intBread(Bread bread){
            // 判断容器有没有满
            if (index >= breads.length){
                // 满了,加入队列
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            breads[index] = bread;
            System.out.println(Thread.currentThread().getName() + "存了一个面包,剩余面包 "+(index + 1) + " 个");
            index ++;
            this.notifyAll();
        }
    
        // 取出面包
        public synchronized void outBread(){
            // 判断容器是否还有面包
            if (index <= 0){
                // 没有面包
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            breads[index - 1] = null;
            System.out.println(Thread.currentThread().getName() + "取了一个面包,剩余面包 "+(index -1) + " 个");
            index --;
            this.notifyAll();
        }
    
        public static void main(String[] args) {
            Runnable add = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        p.intBread(new Bread(i,Thread.currentThread().getName()));
                    }
                }
            };
            Runnable out = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        p.outBread();
                    }
                }
            };
    
            new Thread(add,"小虎").start();
            new Thread(out,"小白").start();
        }
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    在这里插入图片描述

    ⑥:小结

    在这里插入图片描述

    五、线程池

    ①:线程池概念

    在这里插入图片描述

    原理

    在这里插入图片描述

    ②:创建线程池

    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

    package com.example.d10_executor;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class CreateExecutor {
        public static void main(String[] args) {
    
            // 1.创建线程池
            ExecutorService pool = Executors.newFixedThreadPool(5);
            // 2.创建任务
            final int[] index = {0};
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                   while (true){
                           if (index[0] >= 100){
                               break;
                           }
                           System.out.println(Thread.currentThread().getName() + "卖了第" + (index[0] + 1) + "张票");
                           index[0]++;
                   }
                }
            };
            // 3.将任务提交给线程池
            for (int i = 0; i < 4; i++) {
                pool.submit(runnable);
            }
            // 4. 关闭线程池
            pool.shutdown(); // 等待任务所有执行完毕然后关闭线程池
           // pool.shutdownNow(); // 不等待任务执行完毕就会关闭线程池
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    在这里插入图片描述

    ③:Future接口

    在这里插入图片描述## ④:异步和同步

    同步:

    在这里插入图片描述

    异步:

    在这里插入图片描述

    六、Lock接口

    ①:重入锁

    在这里插入图片描述

    package com.example.d9_lock;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    class ReentrantLock2 {
        private Lock lock = new ReentrantLock();
        private String[] strs = {"A","B","","",""};
        private int count = 2;
        public void add(String str){
            lock.lock(); // 开启锁
            try {
                strs[count] = str;
                count++;
                System.out.println(Thread.currentThread().getName() + "添加了元素" + str);
            }finally {
                lock.unlock(); // 释放锁
            }
        }
    
    
        public String[] getStrs() {
            return strs;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    package com.example.d9_lock;
    
    import java.util.Arrays;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class MyLock2 {
        private static ReentrantLock2 rl = new ReentrantLock2();
        public static void main(String[] args) {
            // 创建线程池对象
            ExecutorService pool = Executors.newFixedThreadPool(2);
    
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    rl.add("Word");
                }
            });
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    rl.add("Hello");
                }
            });
    
            pool.shutdown();
    
            String[] strs = rl.getStrs();
            System.out.println(Arrays.toString(strs));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    在这里插入图片描述

    ②:使用Lock完成窗口买票

    方法一:

    package com.example.d9_lock;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class TicketLock {
        private static MyLock3 myLock3 = new MyLock3();
    
        public static void main(String[] args) {
            // 创建线程池
            ExecutorService pool = Executors.newFixedThreadPool(4);
            // 提交任务
            for (int i = 0; i < 4; i++) {
                pool.submit(myLock3);
            }
            // 关闭线程池
            pool.shutdown();
        }
    }
    
    class MyLock3 implements Runnable {
        private static Lock lock = new ReentrantLock();
        private static int number = 0;
    
        @Override
        public void run() {
            while (true) {
                lock.lock(); // 开启锁
                try {
                    if (number >= 1000){
                       break;
                    }
                    System.out.println(Thread.currentThread().getName() + "卖了第" + (number + 1) + "张票");
                    number++;
                } finally {
                    lock.unlock(); //释放锁
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    方法二:

    package com.example.d9_lock;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    public class TicketLock2 {
        private static TicketLock2 ticketLock2 = new TicketLock2();
        private static Lock lock = new ReentrantLock();
        private static int number = 0;
    
        public void ticket(){
            while (true) {
                lock.lock(); // 开启锁
                try {
                    if (number >= 1000){
                        break;
                    }
                    System.out.println(Thread.currentThread().getName() + "卖了第" + (number + 1) + "张票");
                    number++;
                } finally {
                    lock.unlock(); //释放锁
                }
            }
        }
    
        public static void main(String[] args) {
            // 创建线程池
            ExecutorService pool = Executors.newFixedThreadPool(4);
            // 提交任务
            for (int i = 0; i < 4; i++) {
                pool.submit(new Runnable() {
                    @Override
                    public void run() {
                        ticketLock2.ticket();
                    }
                });
            }
            // 关闭线程池
            pool.shutdown();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在这里插入图片描述

    ③:读写锁

    在这里插入图片描述

    01.使用读写锁

    package com.example.readAndWirteLock;
    
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
    
    public class ReadWriteDemo {
        // 创建读写锁
        ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
        // 获取读锁
        private ReadLock readLock = rwl.readLock();
        // 获取写锁
        private WriteLock writeLock = rwl.writeLock();
        private String value;
    
        // 读锁
        public String getValue(){
            readLock.lock();
            try {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("读取:" + value);
                return this.value;
            }finally {
                readLock.unlock();
            }
    
        }
    
        // 写锁
        public void setValue(String value){
            writeLock.lock();
            try{
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("写入:" + value);
                this.value = value;
            }finally {
                writeLock.unlock();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    package com.example.readAndWirteLock;
    
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ReadWriteTest {
        private static Random random = new Random();
        public static void main(String[] args) {
            Long start = System.currentTimeMillis();
            ReadWriteDemo readWriteDemo = new ReadWriteDemo();
            // 创建线程池
            ExecutorService pool = Executors.newFixedThreadPool(200);
    
            // 分配20个写操作
            for (int i = 0; i < 20; i++) {
                pool.submit(new Runnable() {
                    @Override
                    public void run() {
                        readWriteDemo.setValue("小黑: " + random.nextInt(1000));
                    }
                });
            }
    
            // 分配180个读操作
            for (int i = 0; i < 180; i++) {
                pool.submit(new Runnable() {
                    @Override
                    public void run() {
                        readWriteDemo.getValue();
                    }
                });
            }
    
            // 关闭线程池
            pool.shutdown();
    
            while (!pool.isTerminated()){
    
            }
            Long end = System.currentTimeMillis();
            System.out.println("使用读写锁用时:" + (end - start));
    
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    在这里插入图片描述

    02.不使用读写锁

    package com.example.readAndWirteLock;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class ReadWriteDemo {
        private static Lock lock = new ReentrantLock();
        private String value;
    
        // 读锁
        public String getValue(){
            lock.lock();
            try {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("读取:" + value);
                return this.value;
            }finally {
                lock.unlock();
            }
        }
    
        // 写锁
        public void setValue(String value){
            lock.lock();
            try{
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("写入:" + value);
                this.value = value;
            }finally {
                lock.unlock();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    package com.example.readAndWirteLock;
    
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ReadWriteTest {
        private static Random random = new Random();
        public static void main(String[] args) {
            Long start = System.currentTimeMillis();
            ReadWriteDemo readWriteDemo = new ReadWriteDemo();
            // 创建线程池
            ExecutorService pool = Executors.newFixedThreadPool(200);
    
            // 分配20个写操作
            for (int i = 0; i < 20; i++) {
                pool.submit(new Runnable() {
                    @Override
                    public void run() {
                        readWriteDemo.setValue("小黑: " + random.nextInt(1000));
                    }
                });
            }
    
            // 分配180个读操作
            for (int i = 0; i < 180; i++) {
                pool.submit(new Runnable() {
                    @Override
                    public void run() {
                        readWriteDemo.getValue();
                    }
                });
            }
    
            // 关闭线程池
            pool.shutdown();
    
            while (!pool.isTerminated()){
    
            }
            Long end = System.currentTimeMillis();
            System.out.println("不使用读写锁用时:" + (end - start));
    
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    在这里插入图片描述

    七、线程安全的集合

    在这里插入图片描述
    在这里插入图片描述

    ①:问题演示

    package com.example.arrays;
    
    import java.util.ArrayList;
    
    public class Demo1 {
        public static void main(String[] args) {
            // 1.创建arrayList
            ArrayList<String> arrayList = new ArrayList<>();
            // 2.创建线程
            for (int i = 0; i < 20; i++) {
                int temp = i;
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (int i1 = 0; i1 < 10; i1++) {
                            arrayList.add(Thread.currentThread().getName() + "==" + temp);
                            System.out.println(arrayList.toString());
                        }
                    }
                }).start();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    ②:使用Collections中的工具类

    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

    ③: 使用CopyOnWriteArrayList

    在这里插入图片描述

    案例1

    package com.example.arrays;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.stream.Collectors;
    
    public class Demo1 {
        public static void main(String[] args) {
            // 1.创建CopyOnWriteArrayList
            CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
            // 2.创建线程
            for (int i = 0; i < 20; i++) {
                int temp = i;
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (int i1 = 0; i1 < 10; i1++) {
                            list.add(Thread.currentThread().getName() + "==" + temp);
                            System.out.println(list.toString());
                        }
                    }
                }).start();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述

    案例2

    package com.example.arrays;
    
    import java.util.Random;
    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Demo2 {
        public static void main(String[] args) {
            // 创建集合
            CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
            // 创建线程池
            ExecutorService pool = Executors.newFixedThreadPool(5);
            // 创建任务
            for (int i = 0; i < 5; i++) {
                pool.submit(new Runnable() {
                    @Override
                    public void run() {
                        for (int i1 = 0; i1 < 10; i1++) {
                            String str = Thread.currentThread().getName() + new Random().nextInt(100);
                            list.add(str);
                            System.out.println(str);
                        }
                    }
                });
            }
    
            // 关闭线程池
            pool.shutdown();
    
            while (!pool.isTerminated()){}
            System.out.println("集合大小为:"+list.size());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    在这里插入图片描述

    ④:CopyOnWriteArraySet

    在这里插入图片描述

    package com.example.arrays;
    
    import java.util.concurrent.CopyOnWriteArraySet;
    
    public class Demo3 {
        public static void main(String[] args) {
            CopyOnWriteArraySet<String> list = new CopyOnWriteArraySet<>();
            list.add("A");
            list.add("B");
            list.add("C");
            list.add("D");
            list.add("A");
            System.out.println("元素个数:"+list.size());
            System.out.println(list.toString());
    
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    ⑤:Queue接口(队列)

    在这里插入图片描述

    package com.example.arrays;
    
    import java.util.LinkedList;
    import java.util.Queue;
    
    public class Demo4 {
        public static void main(String[] args) {
            // 创建集合
            Queue<String> queue = new LinkedList<>();
            // 添加元素
            queue.add("苹果");
            queue.add("香蕉");
            queue.add("葡萄");
            queue.add("橘子");
            queue.add("榴莲");
            // 获取第一个元素不删除
            System.out.println(queue.peek());
            System.out.println("======================");
            System.out.println("元素个数为:"+queue.size());
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                System.out.println(queue.poll()); // 出队
            }
            System.out.println("元素个数为:"+queue.size()); // 出队后元素个数为0
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    在这里插入图片描述

    ⑥:ConcurrentLinkedQueue的使用

    在这里插入图片描述

    package com.example.arrays;
    
    import java.util.concurrent.ConcurrentLinkedDeque;
    
    public class Demo5 {
        public static void main(String[] args) throws InterruptedException {
            // 创建集合
            ConcurrentLinkedDeque<Integer> deque = new ConcurrentLinkedDeque<>();
            // 创建任务
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i <= 5; i++) {
                        deque.offer(i);
                    }
                }
            });
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 6; i <= 10; i++) {
                        deque.offer(i);
                    }
                }
            });
            // 启动线程
            t1.start();
            t2.start();
    
            t1.join();
            t2.join();
            System.out.println("----------出队----------");
            int size = deque.size();
            for (int i = 0; i < size; i++) {
                System.out.println(deque.poll());
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    在这里插入图片描述

    ⑦:BlockingQueue接口(阻塞队列)

    在这里插入图片描述在这里插入图片描述> 案例1:

    package com.example.arrays;
    
    import java.util.concurrent.ArrayBlockingQueue;
    
    public class Demo6 {
        public static void main(String[] args) throws InterruptedException {
            // 创建一个有界队列,添加元素
            ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(5);
    
            // 添加元素
            queue.put("a");
            queue.put("b");
            queue.put("c");
            queue.put("d");
            queue.put("e");
            System.out.println("已经添加了5个元素~");
            queue.put("f");
            System.out.println("已经添加了6个元素~");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述
    在这里插入图片描述

    案例2 生产者和消费者

    package com.example.arrays;
    
    import java.util.concurrent.ArrayBlockingQueue;
    
    public class Demo7 {
        public static void main(String[] args) {
            // 创建线程
            ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(6);
            // 创建两个线程
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 30; i++) {
                        try {
                            queue.put(i);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "生产了第 " + i + "块面包");
                    }
                }
            }, "小黑");
    
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 30; i++) {
                        try {
                            queue.take();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "消费了第 " + i + "块面包");
                    }
                }
            }, "小白");
    
            // 启动线程
            t1.start();
            t2.start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    在这里插入图片描述

    ⑧:ConcurrentHashMap 线程安全集合

    在这里插入图片描述

    package com.example.arrays;
    
    import java.util.concurrent.ConcurrentHashMap;
    
    public class Demo8 {
        public static void main(String[] args) {
            // 创建集合
            ConcurrentHashMap<String,Integer> hashMap = new ConcurrentHashMap<>();
            // 使用多线程添加数据
            for (int i = 0; i < 6; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (int j = 0; j < 10; j++) {
                            hashMap.put(Thread.currentThread().getName(),j);
                            System.out.println(hashMap);
                        }
                    }
                }).start();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    ⑨:总结

    在这里插入图片描述

  • 相关阅读:
    Guava类库——Table详解
    大数据学习1.0-目录
    【博学谷学习记录】超强总结,用心分享|架构师-RabbitMQ消息可靠性保障
    Nginx+cpolar实现内网穿透多个Windows Web站点端口
    什么专业最适合学网络安全?一篇文章告诉你
    Qt源码阅读(三) 对象树管理
    git clone:SSL: no alternative certificate subject name matches target host name
    【关于Anaconda闪退无法启动】新版本anaconda3中ssl模块缺失的问题
    Vue 使用vue-cli构建SPA项目(超详细)
    含文档+PPT+源码等]精品基于Uniapp+SSM实现的移动端的家庭客栈管理系统实现的App[包运行成功]
  • 原文地址:https://blog.csdn.net/cygqtt/article/details/126026589