6.3 多线程的安全与应用

6.3 多线程的安全与应用

  • 1. 多线程概念
    • 1. 进程
    • 2. 线程
  • 2. 创建多线程
    • 1. 继承Thread类创建线程
    • 2. 实现Runnable接口创建线程
    • 3. Callable接口创建线程
  • 3. 线程同步
    • 1. 同步锁synchronized
    • 2. synchronized的锁对象
  • 4. 线程安全
    • 模拟商品秒杀
  • 5. 线程池应用
    • 1. concurrent
    • 2. FixedThreadPool 定长线程池
    • 3. CachedThreadPool 可缓存线程池
    • 4. SingleThreadExecutor 单线程线程池
    • 5. ScheduledThreadPool 可调度线程池
  • 6. 总结

6.3 多线程的安全与应用_第1张图片

1. 多线程概念

1. 进程

6.3 多线程的安全与应用_第2张图片
6.3 多线程的安全与应用_第3张图片
6.3 多线程的安全与应用_第4张图片

2. 线程

6.3 多线程的安全与应用_第5张图片
6.3 多线程的安全与应用_第6张图片
6.3 多线程的安全与应用_第7张图片

6.3 多线程的安全与应用_第8张图片

2. 创建多线程

6.3 多线程的安全与应用_第9张图片
6.3 多线程的安全与应用_第10张图片

1. 继承Thread类创建线程

6.3 多线程的安全与应用_第11张图片

package com.imooc.thread;

import java.util.Random;

//继承Thread实现多线程程序
public class ThreadSample1 {
    /**
     * 创建跑步线程
     * 继承Thread,重写run方法实现业务需求
     */
    class Runner extends Thread {
        @Override
        public void run() {
            Integer speed = new Random().nextInt(10);
            for (int i = 1; i <= 10; i++) {
                try {
                    Thread.sleep(1000);//使线程休眠,单位:毫秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("第" + i + "秒:" + this.getName() + "已跑到" + (i * speed) + "米(" + speed + "米/秒)");
            }
        }
    }

    /**
     * 创建线程并开启
     *
     * @param ThreadName 自定义线程名
     */
    public void start(String ThreadName) {
        Runner thread = new Runner();//创建跑步线程
        thread.setName(ThreadName);//设置线程名
        thread.start();//开启线程
    }

    public static void main(String[] args) {
        new ThreadSample1().start("选手1");
        new ThreadSample1().start("选手2");
        new ThreadSample1().start("选手3");
        new ThreadSample1().start("选手4");
    }
}

2. 实现Runnable接口创建线程

package com.imooc.thread;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//实现Runnable接口实现多线程程序
public class ThreadSample2 {
	//线程池,容量:20
    private ExecutorService frService = Executors.newFixedThreadPool(20);
    
    class Runner implements Runnable{
        //跑步名称
        private String runName;

        public Runner(String runName) {
            this.runName = runName;
        }

        @Override
        public void run() {
            Integer speed = new Random().nextInt(10);
            for(int i = 1 ; i <= 10 ; i++){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("第" + i + "秒:" + runName + "已跑到" + (i * speed) + "米(" + speed + "米/秒)");
            }
        }
    }

    /**
     * 创建线程并开启
     * @param runerName
     */
    public void start(String runerName){
        Runner runner = new Runner(runerName);//创建线程规则
        Thread thread = new Thread(runner);//创建线程
        thread.start();//开启线程
    }

    /**
     * 平替,代码较少
     * @param runerName
     */
    public void startExecutors(String runerName){
        frService.submit(new Runner(runerName));//创建并开启线程
    }

    public static void main(String[] args) {
        new ThreadSample2().start("选手A");
        new ThreadSample2().start("选手B");
        new ThreadSample2().start("选手C");

        new ThreadSample2().startExecutors("选手1");
        new ThreadSample2().startExecutors("选手2");
        new ThreadSample2().startExecutors("选手3");
    }
}

3. Callable接口创建线程

package com.imooc.thread;

import java.util.Random;
import java.util.concurrent.*;
//实现Callable接口实现多线程程序
public class ThreadSample3 {
    class Runner implements Callable<Integer>{
        public String name;
        @Override
        public Integer call() throws Exception {
            Integer speed = new Random().nextInt(10);
            Integer result = 0;
            for(int i = 1 ; i <= 10 ; i++){
                Thread.sleep(1000);
                result = i * speed;
                System.out.println("第" + i + "秒:" + this.name + "已跑到" + (i * speed) + "米(" + speed + "米/秒)");
            }
            return result;
        }
    }

    public void start() throws ExecutionException, InterruptedException {
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        Runner threadA = new Runner();
        threadA.name = "参赛者A";
        Runner threadB = new Runner();
        threadB.name = "参赛者B";
        Runner threadC = new Runner();
        threadC.name = "参赛者C";
        //利用Future对象获取每一个线程执行后的结果
        Future<Integer> r1 = executorService.submit(threadA);
        Future<Integer> r2 = executorService.submit(threadB);
        Future<Integer> r3 = executorService.submit(threadC);
        //关闭线程池
        executorService.shutdown();
        System.out.println(threadA.name + "累计跑了" + r1.get() + "米");
        System.out.println(threadB.name + "累计跑了" + r2.get() + "米");
        System.out.println(threadC.name + "累计跑了" + r3.get() + "米");
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new ThreadSample3().start();
    }
}

3. 线程同步

1. 同步锁synchronized

6.3 多线程的安全与应用_第12张图片

package com.imooc.thread;

public class SyncSample {

    class Printer{
        //创建锁对象
        Object lock = new Object();
        //synchronized代码块演示,对自定义对象lock上锁
        public void print(){
            //加锁
            synchronized (lock) {
                try {
                    Thread.sleep(500);
                    System.out.print("最");
                    Thread.sleep(500);
                    System.out.print("爱");
                    Thread.sleep(500);
                    System.out.print("晴");
                    Thread.sleep(500);
                    System.out.print("天");
                    Thread.sleep(500);
                    System.out.print("的");
                    Thread.sleep(500);
                    System.out.print("你");
                    Thread.sleep(500);
                    System.out.println("@_^..");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 线程
     */
    class PrintTask implements Runnable{
        public Printer printer;
        @Override
        public void run() {
            printer.print();
        }
    }

    /**
     * 创建多个线程并使用同一个对象资源
     */
    public void start(){
        Printer printer = new Printer();
        for(int i = 0 ; i < 10 ; i++){
            PrintTask task = new PrintTask();
            task.printer = printer;
            Thread thread = new Thread(task);
            thread.start();
        }
    }

    public static void main(String[] args) {
        SyncSample sample = new SyncSample();
        sample.start();
    }
}

2. synchronized的锁对象

6.3 多线程的安全与应用_第13张图片
synchronized 方法-锁对象:this当前对象——使用比较广泛

        //synchronized方法 - 对this当前对象上锁
        public synchronized void print() {
            try {
                Thread.sleep(500);
                System.out.print("最");
                Thread.sleep(500);
                System.out.print("爱");
                Thread.sleep(500);
                System.out.print("晴");
                Thread.sleep(500);
                System.out.print("天");
                Thread.sleep(500);
                System.out.print("的");
                Thread.sleep(500);
                System.out.print("你");
                Thread.sleep(500);
                System.out.println("@_^..");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

synchronized 静态方法,锁对象:该类的字节码对象

        //synchronized静态方法 - 该类的字节码对象Printer.class
        
        public static synchronized void print3() {
            try {
                //Printer.class
                Thread.sleep(500);
                System.out.print("最");
                Thread.sleep(500);
                System.out.print("爱");
                Thread.sleep(500);
                System.out.print("晴");
                Thread.sleep(500);
                System.out.print("天");
                Thread.sleep(500);
                System.out.print("的");
                Thread.sleep(500);
                System.out.print("你");
                Thread.sleep(500);
                System.out.println("@_^..");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

4. 线程安全

6.3 多线程的安全与应用_第14张图片

模拟商品秒杀

6.3 多线程的安全与应用_第15张图片

package com.imooc.thread.mall;

//消费者类
class Consumer implements Runnable{
    //所有消费者都来到同一个商城
    public Mall mall;
    @Override
    public void run() {
        //商城为每一名消费者销售商品
        mall.sale();
    }
}
package com.imooc.thread.mall;
//库存类
public class Stock {
    //当前商品库存剩余3个
    public static int count = 3;
}

package com.imooc.thread.mall;
//模拟商城销售商品
public class Mall {
    public synchronized void sale(){
        if(Stock.count > 0 ){
            try {
                //模拟商城办理销售业务,用时5毫秒
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //销售成功库存减少
            Stock.count--;
            System.out.println("商品销售成功");
        }else{
            System.out.println("商品库存不足,请下次再来吧!");
        }
    }

    public static void main(String[] args) {
        //实例化唯一的商城对象
        Mall mall = new Mall();
        //模拟5名顾客同时涌入商城购买商品
        for(int i = 0 ; i < 100 ; i++){
            Consumer consumer = new Consumer();
            consumer.mall = mall;
            Thread thread = new Thread(consumer);
            thread.start();
        }
        try {
            //模拟下班后判断库存
            Thread.sleep(1000);
            System.out.println("当前商品库存为:" + Stock.count);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

5. 线程池应用

1. concurrent

6.3 多线程的安全与应用_第16张图片
6.3 多线程的安全与应用_第17张图片6.3 多线程的安全与应用_第18张图片
6.3 多线程的安全与应用_第19张图片
6.3 多线程的安全与应用_第20张图片

2. FixedThreadPool 定长线程池

package com.imooc.thread.pool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolSample1 {
    public static void main(String[] args) {
        //创建一个可创建一个定长线程池
        //定长线程池的特点是固定线程总数,空闲线程用于执行任务,如果线程都在使用,后续任务则处于等待状态
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        for(int i = 1; i <= 1000 ; i++){
            final int index = i;
            //不需要返回值,使用execute方法执行Runnable对象
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+":" + index );
                }
            });
            /*
            需要返回值,使用submit方法执行Callable对象,利用Future对象接收返回值
            Future ret = threadPool.submit(new Callable() {
                @Override
                public Object call() throws Exception {
                    return null;
                }
            });
            */
        }
        //处理完毕关闭线程池
        threadPool.shutdown();
    }
}


3. CachedThreadPool 可缓存线程池

package com.imooc.thread.pool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolSample2 {
    public static void main(String[] args) {
        //调度器对象
        //ExecutorService用于管理线程池
        ExecutorService threadPool = Executors.newCachedThreadPool();//创建一个可缓存线程池
        //可缓存线程池的特点是,无限大,如果线程池中没有可用的线程则创建,有空闲线程则利用起来
        for(int i = 1 ; i <= 1000 ; i++) {
            final  int index = i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + ":" + index);
                }
            });
        }
        threadPool.shutdown();
    }
}

4. SingleThreadExecutor 单线程线程池

package com.imooc.thread.pool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolSample3 {
    public static void main(String[] args) {
        //调度器对象
        //ExecutorService用于管理线程池
        ExecutorService threadPool = Executors.newSingleThreadExecutor();//单线程线程池
        for(int i = 1 ; i <= 1000 ; i++) {
            final  int index = i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + ":" + index);
                }
            });
        }
        threadPool.shutdown();
    }
}

5. ScheduledThreadPool 可调度线程池

package com.imooc.thread.pool;

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ThreadPoolSample4 {
    public static void main(String[] args) {
        //调度线程池
        ScheduledExecutorService scheduledThreadPool =  Executors.newScheduledThreadPool(5);//可调度线程池
        //延迟1秒执行,每三秒执行一次
        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println(new Date() + "延迟1秒执行,每三秒执行一次");
            }
        }, 1, 3, TimeUnit.SECONDS);
    }
}

6. 总结

6.3 多线程的安全与应用_第21张图片
在这里插入图片描述

你可能感兴趣的:(Java工程师2022版,java)