狂神说java多线程详解课后笔记

狂神说java多线程

程序 进程 线程

在这里插入图片描述

Process 进程

Thread 线程

多线程核心概念

在这里插入图片描述

java程序在启动时就有main线程和gc垃圾回收线程

线程的创建

在这里插入图片描述

继承Thread类

在这里插入图片描述

//创建一个线程 继承Thread 重写run()方法 调用start 开启线程
//线程开启不一定立即执行 有cpu调度
public class TestThread_01 extends Thread{
    @Override
    public void run() {
//        run方法线程体
        for (int i = 0; i < 10; i++) {
            System.out.println("学习多线程"+i);
        }
    }

    public static void main(String[] args) {
//        创建一个线程对象
        TestThread_01 thread_01 = new TestThread_01();
//        调用start 方法
    thread_01.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("这是主线程"+i);
        }
    }

}

创建一个线程 继承Thread 重写run()方法 调用start 开启线程
线程开启不一定立即执行 由cpu调度

实现Runnable接口

在这里插入图片描述

//创建线程 实现Runnable 接口 重写run方法
public class TestRunnable_01  implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("多线程"+i);
        }
    }

    public static void main(String[] args) {
//        创建runnable接口的实现类对象
        TestRunnable_01 testrunnbale_01 =  new TestRunnable_01();
//        创建线程对象来开启我们的线程代理
        Thread thread_01 = new Thread(testrunnbale_01);
//        开启线程
        thread_01.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("主线程"+i);
        }
    }
}

查看Thread类源码发现也实现了Runbale类

public
class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }

因为java单继承的局限性,所以Thread继承比较局限所以推荐使用Runnable接口实现

在这里插入图片描述

java龟兔赛跑Runnable 接口
package 多线程使用;
//龟兔赛跑
public class Race implements Runnable{
//    胜利者
    static String winner;
    @Override
    public void run() {
        for (int i = 1; i < 105; i++) {
            if(Thread.currentThread().getName().equals("兔子")&&i%30==0){
                try {
//兔子休息一下
                    Thread.sleep(1);
                    System.out.println(Thread.currentThread().getName()+"休息了1毫秒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
//              判断比赛是否结束
            boolean flag = gameover(i);
            if (flag) break;
            System.out.println(Thread.currentThread().getName()+"现在是第:"+i+"步");
        }
    }
    private boolean gameover(int step){
//        判断是否有胜利者
        if(winner !=null){
//            已经存在胜利者
            return true;
        }else {
            if (step == 100){
                winner = Thread.currentThread().getName();
                System.out.println("winner--"+winner+"已经跑了:"+step);
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Race r_01 = new  Race();
        Race r_02 = new  Race();
        new Thread(r_01,"兔子").start();
        new Thread(r_02,"乌龟").start();
    }
}

实现Callable接口

在这里插入图片描述

package 多线程使用;

import java.util.concurrent.*;
/*
使用callable接口实现线程
callable的好处
1可以定义返回值
2可以抛出异常

 */
public class TestCallable implements Callable<Boolean> {
    @Override
    public Boolean call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println("主线程在执行"+i);
        }
        return true;
    }

    public static void main(String[] args) {
        TestCallable call_01 = new TestCallable();
        TestCallable call_02 = new TestCallable();
//        创建执行服务
        ExecutorService ser = Executors.newFixedThreadPool(2);

//        提交执行
        Future<Boolean> future_01 = ser.submit(call_01);
        Future<Boolean> future_02 = ser.submit(call_02);

//        获取结果
        try {
            Boolean res01 = future_01.get();
            Boolean res02 = future_02.get();
            System.out.println(res01);
            System.out.println(res02);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
//        关闭服务
        ser.shutdown();
    }
}

静态代理模式

静态代理模式总结
真实对象和代理对象都要实现同一个接口
代理对象要代理真实角色

代理对象可以做很多真实对象做不了的事情
真实对象专注做自己的事情

package 静态代理;
/*
静态代理模式总结
真实对象和代理对象都要实现同一个接口
代理对象要代理真实角色

代理对象可以做很多真实对象做不了的事情
真实对象专注做自己的事情
 */
public class StaticProxy {
    public static void main(String[] args) {
//        你要结婚
        Me m = new Me();
        /*
        Thread代理真实对象runnable接口 然后调用start方法
         */
        new Thread(()-> System.out.println("我爱你")).start();

        new WeddingCompany(new Me()).HappyMarry();
//
        WeddingCompany wedding = new WeddingCompany(m);
        wedding.HappyMarry();
    }
}
//定义接口
interface Marry{
    void HappyMarry();
}

class Me implements Marry{

    @Override
    public void HappyMarry() {
        System.out.println("秦老师要结婚了无敌开心");
    }
}
//代理角色帮助你结婚
class WeddingCompany implements Marry{
//    代理谁--真实目标角色
    private  Marry target;
    public WeddingCompany(Marry target){
        this.target = target;
    }
    @Override
    public void HappyMarry() {
        bebore();
//        真实对象
        this.target.HappyMarry();
        after();
    }

    private void after() {
        System.out.println("结婚之后收尾款");
    }

    private void bebore() {
        System.out.println("结婚之前布置现场");
    }

}

线程的五大状态

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

使用标志位停止线程,不推荐使用stop() destroy()方法

package 多线程使用;
/*
建议线程正常停止_->利用次数,不建议死循环
建议使用标志位->设置一个标志位
不要使用stop或者destroy过时或者jdk不建议的方法
 */
public class Teststop_thread implements Runnable{
//    设置一个标志位
    private  boolean flag=true;
    @Override
    public void run() {
        while (flag){
            System.out.println("next run...");
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
//    设置一个公开方法停止线程,转换标志位
    public void stop(){
        this.flag=false;
    }

    public static void main(String[] args) {
       Teststop_thread t_01 = new Teststop_thread();

       Thread thread_01 = new Thread(t_01);

       thread_01.start();
        for (int i = 0; i < 200; i++) {
            if(i==100){
//                调用停止方法
                t_01.stop();
            }
            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程休眠

模拟网络延迟 发现问题的发生性

在这里插入图片描述

package 多线程使用;
//模拟网络延迟 发现问题的发生性
public class Testsleep implements Runnable{
    private int number=10;
    @Override
    public void run() {
        while (true){
            if(number<=0)break;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-->拿到了第"+number--+"张票");
        }
    }

    public static void main(String[] args) {
        Testsleep ts = new Testsleep();
        Thread th_01 = new Thread(ts,"小明");
        Thread th_02 = new Thread(ts,"小红");
        Thread th_03 = new Thread(ts,"黄牛");


        th_01.start();
        th_02.start();
        th_03.start();
    }
}

模拟倒计时

package 多线程使用;

public class Testsleep_02 implements Runnable{
    private int number =10;
    @Override
    public void run() {
        try {
            tenDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void tenDown() throws InterruptedException{
        while (true){
            Thread.sleep(100);
            System.out.println(number--);
            if(number<=0) break;
        }
    }

    public static void main(String[] args) {
        Testsleep_02 t1 = new Testsleep_02();

        Thread th = new Thread(t1,"线程1");
        th.start();
    }
}

join方法线程插队

在使用join方法前已经启动的线程是并行的 当前线程使用join方法后会阻塞其他线程 优先执行当前线程

package 多线程使用;
//测试join方法
public class Testjoin implements Runnable{
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println("线程join测试"+i);
        }
    }

    public static void main(String[] args) {
//        启动我们的线程
        Testjoin join_01=new Testjoin();
        Thread th = new Thread(join_01);
        th.start();
//主线程
        for (int i = 0; i < 1000; i++) {

            System.out.println("主线程正在执行"+i);
            if(i==200) {
                try {
                    //            插队
                    th.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

线程状态
  • 线程状态。线程可以处于以下状态之一:

    • NEW
      尚未启动的线程处于此状态。
    • RUNNABLE
      在Java虚拟机中执行的线程处于此状态。
    • BLOCKED
      被阻塞等待监视器锁定的线程处于此状态。
    • WAITING
      正在等待另一个线程执行特定动作的线程处于此状态。
    • TIMED_WAITING
      正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
    • TERMINATED
      已退出的线程处于此状态。

    一个线程可以在给定时间点处于一个状态。 这些状态是不反映任何操作系统线程状态的虚拟机状态。

    线程进入死亡状态不能再次启动

在这里插入图片描述

查看线程状态

package 多线程使用;

public class TestSate implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("子线程"+i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        TestSate test=new TestSate();
        Thread th_01=new Thread(test);
        Thread.State state = th_01.getState();
//        观察状态启动前的状态
        System.out.println(state);
        th_01.start();
//        观察启动后的状态
        state = th_01.getState();
        System.out.println(state);

        while (state !=Thread.State.TERMINATED){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//            更新线程状态
            state = th_01.getState();
            System.out.println(state);

        }
//        死亡之后的线程不能再启动
        th_01.start();
    }
}

线程优先级

在这里插入图片描述

优先级高的不一定会先执行

package 多线程使用;

public class Testpriority {
    public static void main(String[] args) {
//        主线程默认优先级
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
        Mypriority mypriority = new Mypriority();

        Thread th_01 = new Thread(mypriority,"二号线程");
        Thread th_02 = new Thread(mypriority,"三号线程");
        Thread th_03 = new Thread(mypriority,"一号");
        Thread th_04 = new Thread(mypriority,"四号");
        Thread th_05 = new Thread(mypriority,"五号");
//        先设置优先级
        th_01.start();

        th_02.setPriority(1);
        th_02.start();

        th_03.setPriority(4);
        th_03.start();

        th_04.setPriority(Thread.MAX_PRIORITY);
        th_04.start();

        th_05.setPriority(7);
        th_05.start();
    }
}
class Mypriority implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
    }
}

守护线程
  • 一个线程创建时默认为用户线程
  • 通过setDaemon(true)可以将一个线程设置为守护线程
  • java虚拟机会确保用户线程执行完毕
  • java虚拟机不会等待守护线程执行完毕
  • 当用户线程全部结束后,守护线程将会终止
  • 比如后台记录操作日志 监控内存 gc垃圾回收 都是守护线程

在这里插入图片描述

package 多线程使用;
//测试守护线程
public class Testdaemon {
    public static void main(String[] args) {
        God g = new God();
        You y = new You();
        Thread th_01 = new Thread(g);
        Thread th_02 = new Thread(y);
//        设置为守护线程
        th_01.setDaemon(true);
//        守护线程启动了
        th_01.start();

        th_02.start();

        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("真好");
        }
    }
}
class God implements Runnable{

    @Override
    public void run() {
        while (true){
            System.out.println("God保佑你");
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class You implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("你一生都开心得活着");
        }
        System.out.println("goodbye ! word===");
    }
}
并发

同一个线程对象被多个线程同时操作

队列+锁才能保证线程同步的安全性

在这里插入图片描述

在这里插入图片描述

线程不安全例子

例子1

package 多线程使用.线程安全;
//不安全的取钱
public class UnsafeBank {
    public static void main(String[] args) {
//        账户
        Accout accout = new Accout(100, "中国银行");
        Drawing Me = new Drawing(accout,50,"我自己");
        Drawing girlfriend = new Drawing(accout,100,"女朋友");

        Me.start();
        girlfriend.start();
    }
}
//账户
class Accout{
    int money;
    String name;

    public Accout(int money, String name) {
        this.money = money;
        this.name = name;
    }
}
class Drawing extends Thread{
//    账户
    Accout accout;
//    取了多少钱
    int drawingMoney;
//    现在手里还有多少钱
    int nowMoney;
    public Drawing(Accout accout,int drawingMoney,String name){
        this.accout=accout;
        this.drawingMoney=drawingMoney;
        super.setName(name);
    }
//取钱
    @Override
    public void run() {
//        判断有没有钱
        if(accout.money - drawingMoney<0){
            System.out.println(Thread.currentThread().getName()+"钱不够取,取不了");
            return;
        }
//        sleep放大问题的发生性
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

//        卡内余额 = 余额-你取的钱
        accout.money = accout.money-drawingMoney;

        nowMoney=nowMoney+drawingMoney;

        System.out.println(accout.name+"余额为:"+accout.money);
//        Thread.currentThread().getName() == this.getName()
        System.out.println(this.getName()+"手里的钱:"+nowMoney);
    }
}

例子2

package 多线程使用.线程安全;

public class UnsafebuyTicket {
    public static void main(String[] args) {
        BuyTicket ticket = new BuyTicket();
        Thread th_01 = new Thread(ticket, "小明");
        Thread th_02 = new Thread(ticket, "黄牛");
        Thread th_03 = new Thread(ticket, "苦逼的我");

        th_01.start();
        th_02.start();
        th_03.start();

    }
}
class BuyTicket implements Runnable{
//    票
    private int ticketNums =10;
    private boolean flag=false;
    @Override
    public void run() {

//        买票
        while (true){
            buy();
            if(flag) break;
        }
    }
    private void buy(){
//        判断是否有票
        if(ticketNums<=0){
            flag=true;
            return;
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//        买票
        System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
    }
}

例子3

package 多线程使用.线程安全;

import java.util.ArrayList;
import java.util.List;

public class Unsafelist {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
         Thread th =   new Thread(()->{
                list.add(Thread.currentThread().getName());
            });
         th.start();
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

synchronize线程锁

每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

synchronize同步方法

在方法上加修饰词synchronize锁的是当前对象

在这里插入图片描述

同步方法的弊端性能低 因为只需要修改的变量资源才需要上锁

在这里插入图片描述

synchronize同步代码块

同步代码块可以锁任意指定对象

在这里插入图片描述

synchronized代码块同步锁的例子模拟银行操作

package 多线程使用.线程安全;
//不安全的取钱
public class UnsafeBank {
    public static void main(String[] args) {
//        账户
        Accout accout = new Accout(1000, "中国银行");
        Drawing Me = new Drawing(accout,50,"我自己");
        Drawing girlfriend = new Drawing(accout,100,"女朋友");

        Me.start();
        girlfriend.start();
    }
}
//账户
class Accout{
    int money;
    String name;

    public Accout(int money, String name) {
        this.money = money;
        this.name = name;
    }
}
class Drawing extends Thread{
//    账户
    Accout accout;
//    取了多少钱
    int drawingMoney;
//    现在手里还有多少钱
    int nowMoney;
    public Drawing(Accout accout,int drawingMoney,String name){
        this.accout=accout;
        this.drawingMoney=drawingMoney;
        super.setName(name);
    }
//取钱
//    synchronized 修饰方法默认锁的是this
//    synchronized 代码块锁任意指定对象
    @Override
    public void run() {
//        synchronized代码块锁指定对象
//        锁的对象就是变化的量
        synchronized (accout){

            //        判断有没有钱
            if(accout.money - drawingMoney<0){
                System.out.println(Thread.currentThread().getName()+"钱不够取,取不了");
                return;
            }
//        sleep放大问题的发生性
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

//        卡内余额 = 余额-你取的钱
            accout.money = accout.money-drawingMoney;

            nowMoney=nowMoney+drawingMoney;

            System.out.println(accout.name+"余额为:"+accout.money);
//        Thread.currentThread().getName() == this.getName()
            System.out.println(this.getName()+"手里的钱:"+nowMoney);
        }

    }
}

synchronized同步方法的例子模拟买票

package 多线程使用.线程安全;

public class UnsafebuyTicket {
    public static void main(String[] args) {
        BuyTicket ticket = new BuyTicket();
        Thread th_01 = new Thread(ticket, "小明");
        Thread th_02 = new Thread(ticket, "黄牛");
        Thread th_03 = new Thread(ticket, "苦逼的我");

        th_01.start();
        th_02.start();
        th_03.start();

    }
}
class BuyTicket implements Runnable{
//    票
    private int ticketNums =10;
    private boolean flag=false;
    @Override
    public void run() {

//        买票
        while (true){
            buy();
            if(flag) break;
        }
    }
//    synchronized 同步方法
    private synchronized void buy(){
//        判断是否有票
        if(ticketNums<=0){
            flag=true;
            return;
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//        买票
        System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
    }
}

**synchronized 代码块同步锁的例子Arraylist **

ArrayList是线程不安全的,因为多线程在操作list的空间会同时写到同一块内存位置,然后会覆盖掉之前的内容

package 多线程使用.线程安全;

import java.util.ArrayList;
import java.util.List;

public class Unsafelist {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        synchronized(list) {
            for (int i = 0; i < 100; i++) {
                Thread th = new Thread(() -> {

                    list.add(Thread.currentThread().getName());

                });
                th.start();
            }
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

JUC并发下的线程安全的集合CopyOnWriteArrayList

package 多线程使用.线程安全;

import java.util.concurrent.CopyOnWriteArrayList;

//测试juc安全类型的集合
public class TestJuc {
    public static void main(String[] args) {
        CopyOnWriteArrayList list = new CopyOnWriteArrayList<String>();
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

死锁

死锁 多个线程互相抱着对方的需要的资源 ,然后形成互相僵持

package 多线程使用.线程安全;
//死锁 多个线程互相抱着对方的需要的资源 ,然后形成互相僵持
public class DeadLock {
    public static void main(String[] args) {
        Makeup makeup_01 = new Makeup(0, "大美女");
        Makeup makeup_02 = new Makeup(1,"小姐姐");

        makeup_01.start();
        makeup_02.start();
    }
}
//口红
class Lipstick{

}
//镜子
class Mirror{

}
class Makeup extends Thread{
//    需要的资源只有一份,用static来保证
    static Lipstick li =new Lipstick();
    static Mirror mi = new Mirror();
//
    int choice;
    String girlName;
    Makeup(int choice,String girlName){
        this.choice=choice;
        this.girlName=girlName;
    }
    @Override
    public void run() {
        try {
            makeup();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
//    化妆,互相持有对方的锁
    private void makeup() throws InterruptedException {
        if(choice==0){
//            拿到口红的锁
            synchronized (li){
                System.out.println(this.girlName+"获得口红的锁");
                Thread.sleep(1000);
                synchronized (mi){
//                    一秒钟后获得镜子的锁
                    System.out.println(this.girlName+"获得镜子的锁");
                }
            }
        }else {
            synchronized (mi){
                System.out.println(this.girlName+"获得镜子的锁");
                Thread.sleep(2000);
                synchronized (li){
//                    一秒钟后获得镜子的锁
                    System.out.println(this.girlName+"获得口红的锁");
                }
            }
        }

    }
}

在这里插入图片描述

在这里插入图片描述

释放掉对方需要的对象

package 多线程使用.线程安全;
//死锁 多个线程互相抱着对方的需要的资源 ,然后形成互相僵持
public class DeadLock {
    public static void main(String[] args) {
        Makeup makeup_01 = new Makeup(0, "大美女");
        Makeup makeup_02 = new Makeup(1,"小姐姐");

        makeup_01.start();
        makeup_02.start();
    }
}
//口红
class Lipstick{

}
//镜子
class Mirror{

}
class Makeup extends Thread{
//    需要的资源只有一份,用static来保证
    static Lipstick li =new Lipstick();
    static Mirror mi = new Mirror();
//
    int choice;
    String girlName;
    Makeup(int choice,String girlName){
        this.choice=choice;
        this.girlName=girlName;
    }
    @Override
    public void run() {
        try {
            makeup();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
//    化妆,互相持有对方的锁
    private void makeup() throws InterruptedException {
        if(choice==0){
//            拿到口红的锁 
            synchronized (li){
                System.out.println(this.girlName+"获得口红的锁");
                Thread.sleep(1000);
            }
            synchronized (mi){
//                    一秒钟后获得镜子的锁
                System.out.println(this.girlName+"获得镜子的锁");
            }
        }else {
            synchronized (mi){
                System.out.println(this.girlName+"获得镜子的锁");
                Thread.sleep(2000);

            }
            synchronized (li){
//                    一秒钟后获得镜子的锁
                System.out.println(this.girlName+"获得口红的锁");
            }
        }

    }
}

Lock锁

在juc并发包下

// 定义lock可重入锁
private ReentrantLock re = new ReentrantLock();

在这里插入图片描述

synchronized与Lock的对比

在这里插入图片描述

线程通信

在这里插入图片描述

在这里插入图片描述

模拟生产者和消费者

生产者消费者模型->利用缓冲区解决:管程法

package 多线程使用.线程协作;
//测试:生产者消费者模型->利用缓冲区解决:管程法
//生产者 消费者 产品 缓冲区
public class TestPc {
    public static void main(String[] args) {
        SynContainer sy =  new SynContainer();
        new Productor(sy).start();
        new Consumer(sy).start();
    }
}
//生产者
class Productor extends  Thread{
    private SynContainer sy;
    Productor (SynContainer sy){
        this.sy=sy;
    }
    @Override
    public void run() {
        for (int i = 1; i < 100; i++) {
            this.sy.push(new Chicken(i));
            System.out.println("正在生产第:"+i+"只鸡");
        }
    }
}
//消费者
class Consumer extends Thread{
    private SynContainer sy;
    Consumer (SynContainer sy){
        this.sy=sy;
    }

    @Override
    public void run() {
        for (int i = 1; i < 100; i++) {
            System.out.println("正在消费第:"+this.sy.pop().id+"只鸡");

        }
    }
}
//产品
class Chicken{
    int id;

    public Chicken(int id) {
        this.id = id;
    }
}
//缓冲区
class SynContainer{
    Chicken[] ch=new Chicken[10];
    int cont=0;
    public synchronized void push(Chicken chicken){
        if(cont==ch.length){
//            生产满了等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
//     生产产品
        ch[cont]=chicken;
        cont++;
 //        通知消费者消费
        this.notifyAll();
    }
    public synchronized  Chicken pop(){
//        没有产品了等待生产者
        if(cont==0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
//        消费通知生产者生产
        cont--;
        Chicken chicken = ch[cont];

        this.notifyAll();

        return chicken;
    }
}

信号灯发

package 多线程使用.线程协作;

public class Test_pc2 {
    public static void main(String[] args) {
        TV tv = new TV();
        new Player(tv).start();
        new Watcher(tv).start();
    }
}
class Player extends Thread{
    TV t;
    Player (TV t){
        this.t=t;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if(i%3==0){
                t.paly("演员表示节目:"+i);
            }else t.paly("正在播放广告"+i);

        }
    }
}
class Watcher extends Thread{
    TV t;
    Watcher (TV t){
        this.t=t;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            t.watch();
        }
    }
}
class TV{
//    表演的节目
    String voice;
    boolean flag=true;

    public synchronized void paly(String voice){
        if(!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("演员表演:"+voice);
        flag=!flag;
//        通知观众线程观看
        this.voice=voice;
        this.notifyAll();
    }
    public synchronized void watch(){
        if(flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("观众观看:"+this.voice);
        flag=!flag;
//        通知演员生产
        this.notifyAll();

    }

}

线程池的使用

在这里插入图片描述

在这里插入图片描述

package 多线程使用.线程协作;

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

//测试线程池
public class Testpool {
    public static void main(String[] args) {
//        创建服务,创建线程池
//        参数为线程池大小
        ExecutorService pool = Executors.newFixedThreadPool(10);

        pool.execute(new MyThread());
        pool.execute(new MyThread());
        pool.execute(new MyThread());
        pool.execute(new MyThread());
        pool.execute(new MyThread());
//        关闭连接
        pool.shutdown();
    }
}
class MyThread implements Runnable{

    @Override
    public void run() {
            System.out.println(Thread.currentThread().getName());

    }
}

多线程总结

多线程的创建

  • 继承Thread类
  • 实现Runnable接口
  • 实现Callable接口

表演:"+voice);
flag=!flag;
// 通知观众线程观看
this.voice=voice;
this.notifyAll();
}
public synchronized void watch(){
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(“观众观看:”+this.voice);
flag=!flag;
// 通知演员生产
this.notifyAll();

}

}


#### 线程池的使用

[外链图片转存中...(img-xpgsbX0B-1625890820023)]

[外链图片转存中...(img-qGCsJksq-1625890820024)]

```java
package 多线程使用.线程协作;

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

//测试线程池
public class Testpool {
    public static void main(String[] args) {
//        创建服务,创建线程池
//        参数为线程池大小
        ExecutorService pool = Executors.newFixedThreadPool(10);

        pool.execute(new MyThread());
        pool.execute(new MyThread());
        pool.execute(new MyThread());
        pool.execute(new MyThread());
        pool.execute(new MyThread());
//        关闭连接
        pool.shutdown();
    }
}
class MyThread implements Runnable{

    @Override
    public void run() {
            System.out.println(Thread.currentThread().getName());

    }
}

多线程总结

多线程的创建

  • 继承Thread类
  • 实现Runnable接口
  • 实现Callable接口
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值