• 【java】多线程


    进程和线程

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

    继承Thread类的方式实现多线程

    在这里插入图片描述
    MyThread.java

    package heima.多线程;
    
    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
    • 11
    • 12
    package heima.多线程;
    
    public class P1 {
        public static void main(String[] args) {
            MyThread my1 = new MyThread();
            MyThread my2 = new MyThread();
    
    //        my1.run();
    //        my2.run();//1~99
    
            //void start():导致此现场开始执行;java虚拟机调用此线程的run方法
            my1.start();
            my2.start();//1~99
            
            //两者区别
            //run:相当于普通的调用
            //start:启动线程;然后由虚拟机调用此线程的run()方法
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    设置和获取线程的名称

    在这里插入图片描述
    MyThread.java

    package heima.多线程;
    
    public class MyThread extends Thread{
        public MyThread(){}
    
        public MyThread(String name){
            super(name);
        }
        @Override
        public void run(){
            for (int i = 0;i<100;i++){
                System.out.println(getName()+":"+i);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    package heima.多线程;
    
    public class P2 {
        public static void main(String[] args) {
    //        MyThread my1 = new MyThread();
    //        MyThread my2 = new MyThread();
    
            //1.void setName(String name):将此线程的名称更改位大于参数name
    //        my1.setName("高铁");
    //        my2.setName("飞机");
    
            //2.Thread(String name):带参构造方法--需要对MyThread内部进行修改
    //        MyThread my1 = new MyThread("高铁");
    //        MyThread my2 = new MyThread("飞机");
    //
    //        my1.start();
    //        my2.start();
    
            //3.static Thread currentThread():返回对当前正在执行的线程对象的引用
            System.out.println(Thread.currentThread().getName());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    方法1和方法2的输出:
    在这里插入图片描述

    方法3的输出:
    在这里插入图片描述

    线程优先级 线程调度


    ThreadPriority.java

    package heima.多线程;
    
    public class ThreadPriority extends Thread{
        @Override
        public void run() {
            for (int i = 0;i<100;i++){
                System.out.println(getName()+":"+i);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    //后面是输出

    package heima.多线程;
    
    public class P3 {
        public static void main(String[] args) {
            ThreadPriority tp1 = new ThreadPriority();
            ThreadPriority tp2 = new ThreadPriority();
            ThreadPriority tp3 = new ThreadPriority();
    
            tp1.setName("高铁");
            tp2.setName("飞机");
            tp3.setName("汽车");
    
    //        tp1.start();
    //        tp2.start();
    //        tp3.start();
    
            //public final int getPriority():返回此线程的优先级
    //        System.out.println(tp1.getPriority());//5
    //        System.out.println(tp2.getPriority());//5
    //        System.out.println(tp3.getPriority());//5
    //
    //        //public final void setPriority(int newPriority):更改此线程的优先级
            tp1.setPriority(10000);//IllegalArgumentException
    //        System.out.println(Thread.MAX_PRIORITY);//10
    //        System.out.println(Thread.MIN_PRIORITY);//1
    //        System.out.println(Thread.NORM_PRIORITY);//5
    
            //正确设置优先级
            tp1.setPriority(5);
            tp2.setPriority(10);
            tp3.setPriority(1);
    
            tp1.start();
            tp2.start();
            tp3.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

    计算设置了优先级也同样还是有随机性,需要在次数较多的时候才能看到想要的效果

    控制线程

    在这里插入图片描述

    • sleep
    package heima.多线程.other;
    
    public class ThreadSleep extends Thread{
        @Override
        public void run() {
            for (int i = 0;i<100;i++){
                System.out.println(getName()+":"+i);
                try {
                    //sleep使三人轮流抢到cpu时间,看上去更加和谐
                    Thread.sleep(1000);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    package heima.多线程;
    
    import heima.多线程.other.ThreadSleep;
    
    public class P4 {
        public static void main(String[] args) {
            ThreadSleep ts1 = new ThreadSleep();
            ThreadSleep ts2 = new ThreadSleep();
            ThreadSleep ts3 = new ThreadSleep();
    
            ts1.setName("曹操");
            ts2.setName("刘备");
            ts3.setName("孙权");
    
            ts1.start();
            ts2.start();
            ts3.start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • join
    package heima.多线程;
    
    import heima.多线程.other.ThreadSleep;
    
    public class P4 {
        public static void main(String[] args) {
            ThreadSleep ts1 = new ThreadSleep();
            ThreadSleep ts2 = new ThreadSleep();
            ThreadSleep ts3 = new ThreadSleep();
    
            ts1.setName("曹操");
            ts2.setName("刘备");
            ts3.setName("孙权");
    
            ts1.start();
            //void join():等待这个线程死亡
            try{
                ts1.join();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            ts2.start();
            ts3.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

    在这里插入图片描述

    • setDaemon
    package heima.多线程;
    
    import heima.多线程.other.ThreadSleep;
    
    public class P4 {
        public static void main(String[] args) {
            ThreadSleep ts1 = new ThreadSleep();
            ThreadSleep ts2 = new ThreadSleep();
            ThreadSleep ts3 = new ThreadSleep();
    
            ts1.setName("关羽");
            ts2.setName("张飞");
    
            //设置主线程为刘备
            Thread.currentThread().setName("刘备");
    
            //设置守护线程
            ts1.setDaemon(true);
            ts2.setDaemon(true);
    
            ts1.start();
            ts2.start();
    
            for (int i = 0;i<10;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
    
    
    • 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

    线程的生命周期

    在这里插入图片描述

    多线程的实现方式

    在这里插入图片描述

    在这里插入图片描述
    MyRunnable.java

    package heima.多线程.other;
    
    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
    • 11
    package heima.多线程;
    
    import heima.多线程.other.MyRunnable;
    
    public class P5 {
        public static void main(String[] args) {
            //创建MyRunnable类的对象
            MyRunnable my = new MyRunnable();
    
            //创建Thread类的对象,吧MyRunnable对象作为构造方法的参数
            //Thread(Runnable target)
    //    Thread t1 = new Thread(my);
    //    Thread t2 = new Thread(my);
            //Thread(Runnable target,String name)
            Thread t1 = new Thread(my,"高铁");
            Thread t2 = new Thread(my,"飞机");
    
            //启动线程
            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

    案例–卖票

    在这里插入图片描述

    package heima.多线程;
    
    import heima.多线程.other.SellTicket;
    
    public class P6 {
        public static void main(String[] args) {
            //创建SellTicket类的对象
            SellTicket st = new SellTicket();
    
            //创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
            Thread t1 = new Thread(st,"窗口1");
            Thread t2 = new Thread(st,"窗口2");
            Thread t3 = new Thread(st,"窗口3");
    
            //启动线程
            t1.start();
            t2.start();
            t3.start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    package heima.多线程.other;
    
    public class SellTicket implements Runnable{
        //在SellTicket类中重写run()实现卖票
        private int tickets = 100;
    
        @Override
        public void run() {
            while (true){
                if (tickets > 0){
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                    tickets--;
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 卖票案例的改进

    在这里插入图片描述

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

    package heima.多线程.other;
    
    public class SellTicket implements Runnable{
        //在SellTicket类中重写run()实现卖票
        private int tickets = 100;
        private Object obj = new Object();
    
        @Override
        public void run() {
            //加上代码锁,使每次只能进来一个对象
            synchronized (obj){
                while (true){
                    if (tickets > 0){
                        try {
                            //让卖票动作更符合现实情况
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                        tickets--;
                    }
                }
            }
        }
    }
    
    
    • 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

    在这里插入图片描述

    同步方法解决数据安全问题

    在这里插入图片描述

    详情请见 黑马P334

    线程安全的类

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

    Lock锁

    在这里插入图片描述

    package heima.多线程.other;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class SellTicket implements Runnable{
        //在SellTicket类中重写run()实现卖票
        private int tickets = 100;
        private Object obj = new Object();
        private Lock lock = new ReentrantLock();
    
        @Override
        public void run() {
            while (true){
                try {
                    lock.lock();
                    if (tickets > 0){
                        try {
                            Thread.sleep(100);
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                        tickets--;
                    }
                //最后使用finally,使得就算报错最后也可以关闭锁
                }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

    生产者消费者模式

    概述

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

    案例

    在这里插入图片描述

    • 步骤1:先创建好基本的框架

    BoxDemo.java

    package heima.生产者消费者;
    
    public class BoxDemo {
        public static void main(String[] args) {
            //创建奶箱对象,这是共享数据区域
            Box b = new Box();
    
            //创建生产者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作
            Producter p = new Producter(b);
    
            //创建消费者对象,把奶箱对象作为构造方法参数传递,以为在这个类中要调用获取牛奶的操作
            Customer c = new Customer(b);
    
            //创建两个线程对象,分别把生产者和消费者对象作为构造方法参数传递
            Thread t1 = new Thread(p);
            Thread t2 = new Thread(c);
    
            //启动线程
            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

    Customer.java

    package heima.生产者消费者;
    
    public class Customer implements Runnable{
        private Box b;
        public Customer(Box b){
            this.b = b;
        }
        @Override
        public void run() {
            while (true) {
                b.get();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Producter.java

    package heima.生产者消费者;
    
    public class Producter implements Runnable{
        private Box b;
    
        public Producter(Box b){
            this.b = b;
        }
        @Override
        public void run() {
            for (int i = 1;i<=5;i++){
                b.put(i);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Box.java

    package heima.生产者消费者;
    
    public class Box {
        //定义一个成员变量,表示第x瓶奶
        private int milk;
    
        //提供存储牛奶和获取牛奶的操作
        public void put(int milk){
            this.milk = milk;
            System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱");
        }
    
        public void get(){
            System.out.println("用户拿到第"+this.milk+"瓶奶");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    输出一直卡死在最后的第5瓶奶上:
    在这里插入图片描述

    • 步骤2
    1. 定义奶箱状态,并进行状态判断是否等待
    2. 等待需要配对对应的锁:synchronized
    3. 在等待的同步需要:唤醒其他等待的线程notifyAll

    完整版

    package heima.生产者消费者;
    
    public class Box {
        //定义一个成员变量,表示第x瓶奶
        private int milk;
        //定义一个成员变量,表示奶箱的状态
        private boolean state = false;
    
        //提供存储牛奶和获取牛奶的操作
        public synchronized void put(int milk){
            //如果有牛奶,等待消费
            if (state){
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            //如果没有牛奶,就生产牛奶
            this.milk = milk;
            System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱");
    
            //生产完毕之后,修改牛奶的状态
            state = true;
    
            //唤醒其他等待的线程
            notifyAll();
        }
    
        public synchronized void get() {
            //如果没有牛奶,等待生产
            if (!state) {
                try {
                    wait();
    
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            //如果有牛奶,就消费牛奶
            System.out.println("用户拿到第" + this.milk + "瓶奶");
    
            //消费完毕之后,修改奶箱状态
            state = false;
    
            //唤醒其他等待的线程
            notifyAll();
        }
    }
    
    
    • 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
    package heima.生产者消费者;
    
    public class Producter implements Runnable{
        private Box b;
    
        public Producter(Box b){
            this.b = b;
        }
        @Override
        public void run() {
            for (int i = 1;i<=5;i++){
                b.put(i);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    package heima.生产者消费者;
    
    public class Customer implements Runnable{
        private Box b;
        public Customer(Box b){
            this.b = b;
        }
        @Override
        public void run() {
            while (true) {
                b.get();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    package heima.生产者消费者;
    
    public class BoxDemo {
        public static void main(String[] args) {
            //创建奶箱对象,这是共享数据区域
            Box b = new Box();
    
            //创建生产者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作
            Producter p = new Producter(b);
    
            //创建消费者对象,把奶箱对象作为构造方法参数传递,以为在这个类中要调用获取牛奶的操作
            Customer c = new Customer(b);
    
            //创建两个线程对象,分别把生产者和消费者对象作为构造方法参数传递
            Thread t1 = new Thread(p);
            Thread t2 = new Thread(c);
    
            //启动线程
            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

    在这里插入图片描述

  • 相关阅读:
    K8S之Deployment控制pod
    剑指offer——JZ32 从上往下打印二叉树 解题思路与具体代码【C++】
    2020年12月大学英语六级作文
    线程的状态
    使用Dockerfile生成docker镜像和容器的方法记录
    GL Studio 5 安装与体验
    中科创达C++ 一面(技术面、24min)
    【shell脚本编写】shell 数组的使用
    docker 操作redis
    将json-bigint处理为数值分区数组的字段全部自动转为字符串
  • 原文地址:https://blog.csdn.net/m0_65431212/article/details/128125981