2021.6.3笔记 多线程


☀并发与并行

在这里插入图片描述


☀进程概念

在这里插入图片描述


☀线程概念

在这里插入图片描述


☀线程调度

在这里插入图片描述


☀主线程

在这里插入图片描述
在这里插入图片描述
ps:单线程的缺点就是当代码中出现异常,那么之后的代码将运行不了


☀创建Thread类的子类

在这里插入图片描述

public class ThreadClass extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println("run" + i);
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
        ThreadClass thr = new ThreadClass();
        thr.start();
        for (int i = 0; i < 50; i++) {
            System.out.println("main" + i);
        }
    }
}

在这里插入图片描述

ps:上面的循环次数如果太少,可能看不到main和run抢占cpu执行的过程…


☀实现runnable接口

在这里插入图片描述

public class RunnableClass implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }
    }
}
public class RunnableObj {
    public static void main(String[] args) {
        RunnableClass newObj = new RunnableClass();
        Thread newThread = new Thread(newObj);
        newThread.start();

        for (int i = 0; i < 50; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }
    }
}

☀Thread和Runnable的区别

在这里插入图片描述


☀匿名内部类方式实现线程的创建

在这里插入图片描述

public class EnoClass {
    public static void main(String[] args) {
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName() + "--> 小新");
                }
            }
        }.start();

        Runnable rn = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName() + "--> 风间");
                }
            }
        };
        new Thread(rn).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName() + "--> 妮妮");
                }
            }
        }).start();
    }
}

☀多线程内存图

在这里插入图片描述


☀Thread类的常用方法

获取线程名称的方法

在这里插入图片描述1.直接getName

public class Thread01 extends Thread{
    @Override
    public void run() {
        String name = getName();
        System.out.println(name);
    }
}
public class Thread02 {
    public static void main(String[] args) {
        Thread01 thr01 = new Thread01();
        thr01.start();
        new Thread01().start();
    }
}

2.借助currentThread和getName

public class Thread01 extends Thread{
    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        String name = thread.getName();
        System.out.println(name);
        /*System.out.println(Thread01.currentThread().getName());链式编程*/
    }
}
public class Thread02 {
    public static void main(String[] args) {
        Thread01 thr01 = new Thread01();
        thr01.start();
        new Thread01().start();
    }
}

设置线程名称的方法(了解即可)

在这里插入图片描述

public class SetNameThread extends Thread{
    public SetNameThread() {

    }
    public SetNameThread(String name) {
        super(name);
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
public class SetName {
    public static void main(String[] args) {
        SetNameThread newThread = new SetNameThread();
        newThread.setName("小新");
        newThread.start();

        new SetNameThread("妮妮").start();
    }
}

sleep方法

在这里插入图片描述

public class SleepDemo {
    public static void main(String[] args) {
        for (int i = 0; i < 60; i++) {
            System.out.println(i);
            try {
                Thread.sleep(1000);     //单位:毫秒,需要抛出异常或者try...catch
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

☀线程安全问题

图解和代码实现

在这里插入图片描述

public class RunnableClass implements Runnable{
    private int tickNum = 100;
    @Override
    public void run() {
        while (true) {
            if(tickNum > 0) {
                try {
                    Thread.sleep(10);       //不用sleep的时候会重复卖票,用sleep出现负数和0,具体原因待定
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "--> 正在卖第" + tickNum + "张票。");
                tickNum--;
            }
        }
    }
}
public class RunnableObj {
    public static void main(String[] args) {
        RunnableClass run = new RunnableClass();
        Thread thread1 = new Thread(run);
        Thread thread2 = new Thread(run);
        Thread thread3 = new Thread(run);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

但是这里面用的死循环我有点难理解,就算代码执行完了,由于是死循环,系统依旧一直在判定是否满足执行条件,这样会大大浪费系统资源,所以待定看看。目前看来,个人猜想,这样做的原因是因为执行的次数未知(因为可能有重复的票以及负数和0的票),所以才选择这样的方式。

原理

在这里插入图片描述

解决方法一——同步代码块

图解及代码实现

在这里插入图片描述

public class RunnableClass implements Runnable{
    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        while (true) {
            synchronized (obj) {
                if(ticket > 0) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
                    ticket--;
                }
            }
        }
    }
}
public class NewObj {
    public static void main(String[] args) {
        RunnableClass run = new RunnableClass();
        Thread thread1 = new Thread(run);
        Thread thread2 = new Thread(run);
        Thread thread3 = new Thread(run);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

原理

在这里插入图片描述

解决方法二——同步方法

在这里插入图片描述

public class RunnableClass implements Runnable{
    private int ticket = 100;
    @Override
    public void run() {
        while (true) {
            method();
        }
    }
    public synchronized void method() {
        if(ticket > 0) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
            ticket--;
        }
    }
}
public class NewObj {
    public static void main(String[] args) {
        RunnableClass run = new RunnableClass();
        Thread thread1 = new Thread(run);
        Thread thread2 = new Thread(run);
        Thread thread3 = new Thread(run);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

ps:验证锁对象是否为this

public class RunnableClass implements Runnable{
    private int ticket = 100;
    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                method();
            }
        }
    }
    public /*synchronized*/ void method() {
        if(ticket > 0) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
            ticket--;
        }
    }
}

静态同步方法

在这里插入图片描述

public class RunnableClass implements Runnable{
    private static int ticket = 100;       //变量也要是静态的
    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                method();
            }
        }
    }
    public static synchronized void method() {          //静态同步方法
        if(ticket > 0) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
            ticket--;
        }
    }
}

解决方法三——Lock锁

在这里插入图片描述

public class RunnableClass implements Runnable{
    private int ticket = 100;
    Lock newLock = new ReentrantLock();		//多态
    @Override
    public void run() {
        while (true) {
            newLock.lock();
            if(ticket > 0) {
                try {
                    Thread.sleep(10);
                    System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
                    ticket--;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    newLock.unlock();
                }
            }
        }
    }
}

☀线程状态概述

在这里插入图片描述


☀等待唤醒案例分析

在这里插入图片描述

代码实现

在这里插入图片描述

public class NewClass {
    public static void main(String[] args) {
        Object obj = new Object();
        new Thread() {
            @Override
            public void run() {
                System.out.println("我想要一份烧饼");
                synchronized (obj) {
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("吃完了,很好吃");
                    }
                }
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (obj) {
                    System.out.println("烧饼做好了,吃吧");
                    obj.notify();
                }
            }
        }.start();
    }
}

想要重复执行用while(true)死循环。


☀Object类中wait带参方法和notifyAll方法

在这里插入图片描述

public class NewClass {
    public static void main(String[] args) {
        Object obj = new Object();
        new Thread() {
            @Override
            public void run() {
                System.out.println("顾客1:我想要一份烧饼");
                synchronized (obj) {
                    try {
                        obj.wait(6000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        System.out.println("顾客1:吃完了,很好吃");
                    }
                }
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                System.out.println("顾客2:我想要一份烧饼");
                synchronized (obj) {
                    try {
                        obj.wait(6000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        System.out.println("顾客2:吃完了,很好吃");
                    }
                }
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (obj) {
                    System.out.println("烧饼做好了,吃吧");
                    obj.notifyAll();
                }
            }
        }.start();
    }
}

在这里插入图片描述


☀等待唤醒机制

在这里插入图片描述

public class Baozi {
    String pi;
    String xian;
    boolean isExist = false;
}
public class BaoZiPu extends Thread{
    private Baozi bz;

    public BaoZiPu(Baozi bz) {
        this.bz = bz;
    }

    @Override
    public void run() {
        int count = 0;
        while(true) {
            synchronized (bz) {
                if (bz.isExist == true) {
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                if(count % 2 == 0) {
                    bz.pi = "薄皮";
                    bz.xian = "韭菜馅";
                }else {
                    bz.pi = "厚皮";
                    bz.xian = "猪肉馅";
                }
                count++;
                System.out.println("包子铺在生产" + bz.pi + bz.xian + "包子");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                bz.isExist = true;
                bz.notify();
                System.out.println("包子铺生产好了:" + bz.pi + bz.xian + "包子");
            }
        }
    }
}
public class Chihuo extends Thread{
    private Baozi bz;

    public Chihuo(Baozi bz) {
        this.bz = bz;
    }

    @Override
    public void run() {
        while(true) {
            synchronized (bz) {
                if(bz.isExist == true) {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("我开吃了");
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    bz.isExist =  false;
                    bz.notify();
                    System.out.println("吃完了");
                }else {
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
public class DetectDemo {
    public static void main(String[] args) {
        Baozi bz = new Baozi();
        new BaoZiPu(bz).start();
        new Chihuo(bz).start();
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值