java里面的多线程

目录

线程的简介:

多任务:

多线程:

普通方法调用​

多线程: ​

核心概念:

线程的创建

Thread: ​

代码:

注意:

实现Runnable接口:

代码:

小结:

初识并发问题:

代码:

运行的结果:

 龟兔赛跑:

步骤:

实现Callable接口(了解即可) 

代码:

 静态代理模式:

静态代理模式总结:

好处:

线程的五大状态:

 方法:​

 线程的停止:

 代码:

 线程休眠:

倒计时的代码:

模拟网络延时:

线程礼让:

 代码:

运行的结果是:

礼让成功:​

礼让失败: ​

Join 

代码:

 线程状态观测:

 代码:

线程的优先级:

注意:

代码:

 运行的结果:

注意:

 守护线程(daemon):

代码:

线程同步:

并发:

三大不安全例子: 

不安全的买票:

不安全的取钱:

输出的结果是: ​

线程不安全的集合:

运行的结果:

 同步方法及同步块:

 同步代码的弊端:​

同步块:​

 安全的买票:

安全的取钱:

代码:

以下是ai做出的回应:

 运行的结果:​

死锁:​

代码:

运行的结果:

解决的方法:

运行的结果:​

死锁避免的方法:​

Lock锁:

代码演示:

注意事项:

synchronized和Lock的对比:

线程协作:

线程通信:​

线程通信-分析:​

 java提供了几个方法解决线程之间的通信问题:​

 解决方式1:

代码:

解决方式2:​

代码: 

运行结果: ​

 线程池:

 使用线程池:

代码:

运行结果:


线程的简介:

多任务:

java里面的多线程_第1张图片

看起来是多个任务都在做,其实本质上我们的大脑在同一时间依旧只做一件事情

多线程:

java里面的多线程_第2张图片

原来是一条道路,慢慢因为车太多了,道路堵塞,效率较低,为了提高使用的效率,能够充分利用道路,于是加了多个车道.

普通方法调用
java里面的多线程_第3张图片

多线程:
 java里面的多线程_第4张图片

进程是系统分配的 进程里面有线程, 至少有一个线程(main),真正执行的是线程,真正的多线程是指有多个cpu,也就是多核,比如服务器.如果是模拟出来的线程,即在一个cpu的情况下,在同一时间点,cpu执行一个代码,因为切换的很快,所以就有同时执行的错觉.

核心概念:

  • 线程就是独立的执行路径
  • 在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc(垃圾回收)线程
  • main()称之为主线程,为系统的入口,用于执行整个线程
  • 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为干涉的
  • 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制 2
  • 线程会带来额外的开销,如cpu调度时间,并发控制开销
  • 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

线程的创建

java里面的多线程_第5张图片

Thread:
 java里面的多线程_第6张图片

代码:

public class MyThread extends Thread {
    @Override
    public void run() {
         for(int i = 1; i <= 20; ++ i ) {
          System.out.println("Code1: " + i );
         }
    }

    public static void main(String[] args) {
     //创建线程对象
     MyThread thread = new MyThread();
     //开启线程
     thread.start();

     for(int i = 1; i <= 20; ++ i ) {
         System.out.println("Code2: " + i);
     }
     //以上两个线程是同时执行的 每次执行的结果都是不一样的
    }
}

注意:

线程开启后,不一定立刻执行,由cpu调度安排

实现Runnable接口:

java里面的多线程_第7张图片

代码:

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for(int i = 1; i <= 100; ++ i ) {
            System.out.println("Code change the word");
        }
    }

    public static void main(String[] args) {

        MyRunnable myRunnable = new MyRunnable();
        new Thread(myRunnable).start();

        for(int i = 1; i <= 100; ++ i ) {
            System.out.println("我认为你说的对");
        }
    }
}

小结:

java里面的多线程_第8张图片

初识并发问题:

代码:

//多线程同时操作同一个对象
//买火车票的例子
public class TestThread implements Runnable{
    private int ticketNums = 10;//票的数量

    @Override
    public void run() {
        while (true) {
            if(ticketNums <= 0) {//没票了
                break;
            }
            System.out.println(Thread.currentThread().getName() + "购买了第" + ticketNums-- +"票");
        }
    }

    public static void main(String[] args) {
        TestThread ticket = new TestThread();

        //创建买票的对象 这3个线程用这10张票
        new Thread(ticket, "用户1").start();
        new Thread(ticket, "用户2").start();
        new Thread(ticket,"用户3").start();
    }
}

运行的结果:

发现有不同的人拿到相同的票的,也就是多个线程操作同一个资源的情况下,线程不安全,数据紊乱

 龟兔赛跑:

步骤:

java里面的多线程_第9张图片

public class Race implements Runnable{
    private static String winner;
    @Override
    public void run() {
        for(int i = 1; i <= 100; ++ i ) {
            //模拟兔子休息
            if(Thread.currentThread().getName().equals("兔子") && i % 10 == 0) {//每10步休息0.2s
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //判断比赛时候结束
            boolean flag = gameOver(i);
            //如果比赛结束 就停止程序
            if(flag) {
                break;
            }
            System.out.println(Thread.currentThread().getName() + "-->跑了" + i + "米");
        }
    }
    //判断是否完成比赛了
    private boolean gameOver(int steps) {
        if(winner != null) {
            return true;
        }
        if(steps >= 100) {
            winner = Thread.currentThread().getName();
            System.out.println("胜利者是: " + winner);
            return true;
        }
        return false;
    }
    public static void main(String[] args) {
        Race race = new Race();//赛道只有一条
        new Thread(race, "兔子").start();
        new Thread(race, "乌龟").start();
    }
}
//兔子睡觉了 胜利者是乌龟

实现Callable接口(了解即可) 

java里面的多线程_第10张图片

代码:

package 线程;
//实现Callable接口

import java.util.concurrent.*;

public class MyCallable implements Callable {

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for(int i = 1; i <= 100; i ++ ) {
            sum += i;
        }
        return sum;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable t1 = new MyCallable();
        MyCallable t2 = new MyCallable();
        MyCallable t3 = new MyCallable();

        //创建执行服务 线程池
        ExecutorService ser = Executors.newFixedThreadPool(3);

        //提交执行
        Futureresult1 = ser.submit(t1);
        Futureresult2 = ser.submit(t2);
        Futureresult3 = ser.submit(t3);

        //获取结果
        int r1 = result1.get();
        int r2 = result2.get();
        int r3 = result3.get();

        //关闭服务
        ser.shutdownNow();
    }
}

 静态代理模式:

public class StaticProxy {
    public static void main(String[] args) {
        You you = new You();//你要结婚了

        new Thread(()-> System.out.println("I love you")).start();
        
        new WeddingCompany(new You()).HappyMarry();
    }
}

interface Marry {
    void HappyMarry();
}
//真实角色
class You implements Marry {

    @Override
    public void HappyMarry() {
        System.out.println("FindYou.要结婚啦");
    }
}

//代理角色 帮助你
class WeddingCompany implements Marry {
    private Marry target;
    public WeddingCompany(Marry target) {
        this.target = target;
    }
    @Override
    public void HappyMarry() {
        before();
        target.HappyMarry();//真实对象
        after();
    }

    private void before() {
        System.out.println("结婚之前,布置现场");
    }
    private void after() {
        System.out.println("结婚之后,收尾款");
    }
}

静态代理模式总结:

真实对象和代理对象都要实现同一个接口
代理对象要代理真实角色

好处:

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

线程的五大状态:

java里面的多线程_第11张图片

java里面的多线程_第12张图片

 方法:
java里面的多线程_第13张图片

 线程的停止:

java里面的多线程_第14张图片

 代码:

//测试stop
//建议线程正常停止
//不要实现stop和destroy等过时的
public class TestStop implements Runnable {
    //设置一个标识位
    private boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag) {
            System.out.println("run......Thread" + ++ i );
        }
    }
    //转换标识位
    public void stop() {
        flag = false;
    }
    public static void main(String[] args) {
        TestStop testStop = new TestStop();
        new Thread(testStop).start();

        for(int i = 1; i <= 100; ++ i ) {
            System.out.println("main" + i);
            if(i == 50) {
                testStop.stop();//切换标识位 停止线程
                System.out.println("线程要停止啦");
            }
        }
    }
}

 线程休眠:

java里面的多线程_第15张图片

倒计时的代码:

//模拟倒计时
public class Sleep {
    public static void tenDown() throws InterruptedException {
        int num = 10;
        while(true) {
            Thread.sleep(1000);//线程延迟
            System.out.println(num--);
            if(num == 0)break;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        tenDown();
    }
}

模拟网络延时:

放大问题的发生性

线程礼让:

java里面的多线程_第16张图片

 代码:

public class TestYield {
    public static void main(String[] args) {
        MyYield m1 = new MyYield();
        MyYield m2 = new MyYield();

        new Thread(m1, "m1").start();
        new Thread(m2, "m2").start();
    }
}

class MyYield implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程开始执行");
        Thread.yield();//线程礼让
        System.out.println(Thread.currentThread().getName() + "线程停止执行");
    }
}

运行的结果是:


礼让成功:
java里面的多线程_第17张图片
礼让失败:
 java里面的多线程_第18张图片

Join 

java里面的多线程_第19张图片

代码:

public class TestJoin implements Runnable{
    @Override
    public void run() {
        for(int i = 1; i <= 1000; ++ i ) {
            System.out.println("VIP来了" + i);
        }
    }

    public static void main(String[] args) {
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();

        //主线程
        for(int i = 1; i <= 500; ++ i ) {
            if(i == 200) {
                //插队啦 要跑完的 很霸道 
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("main " + i );
        }
    }
}

 线程状态观测:

java里面的多线程_第20张图片

 代码:

//观察测试线程的状态

public class TestState {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
            for(int i = 1; i <= 5; ++ i ) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("!!!!!!");
        });

        //观察启动前现成的状态
        Thread.State state = thread.getState();
        System.out.println(state);

        //观察启动后线程的状态
        thread.start();//启动线程
        state = thread.getState();
        System.out.println(state);

        while (state != Thread.State.TERMINATED) {//只要线程不终止 就一直输出状态
            Thread.sleep(100);
            state = thread.getState();
            System.out.println(state);
        }
        //线程一旦进入死亡状态就不能在启动了
    }
}

线程的优先级:

java里面的多线程_第21张图片

注意:

优先级大,并不一定被执行,只不过概率变大了 

代码:

package 线程;

public class TestPriority {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName() + "的优先级--> " + Thread.currentThread().getPriority());//main的优先级默认是5

        Thread t1 = new Thread(new myPriority());
        Thread t2 = new Thread(new myPriority());
        Thread t3 = new Thread(new myPriority());
        Thread t4 = new Thread(new myPriority());
        Thread t5 = new Thread(new myPriority());
        Thread t6 = new Thread(new myPriority());

        t1.start();//不设优先级

        t2.setPriority(1);//设优先级为4
        t2.start();

        t3.setPriority(4);
        t3.start();

        t4.setPriority(Thread.MAX_PRIORITY);//优先级最高是10
        t4.start();

        t5.setPriority(11);//超出优先级的范围[1 10] 会报异常
        t5.start();

        t6.setPriority(0);//超出优先级的范围[1 10] 会报异常
        t6.start();
    }
}

class myPriority implements Runnable {

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

 运行的结果:

优先级高的并不一定先被执行

java里面的多线程_第22张图片

超出范围会报异常

java里面的多线程_第23张图片

注意:

java里面的多线程_第24张图片

 守护线程(daemon):

java里面的多线程_第25张图片

代码:

//测试守护线程

public class TestDaemon {
    public static void main(String[] args) {
        God god = new God();
        You1 you1 = new You1();


        Thread thread = new Thread(god);
        thread.setDaemon(true);//默认是false 表示的是用户线程 正常的线程都是用户线程
        thread.start();//上帝守护线程启动
        //注意 虚拟机不用等待守护线程执行完毕

        new Thread(you1).start();//用户线程启动...
    }
}

//上帝
class God implements Runnable {
    @Override
    public void run() {
        while(true) {
            System.out.println("上帝保佑着你");
        }
    }
}

//你
class You1 implements Runnable {
    @Override
    public void run() {
        for(int i = 1; i <= 36500; ++ i ) {
            System.out.println("祝福各位开心度过每一天");
        }
        System.out.println("下辈子见 goodbye world");
    }
}
//虚拟机停止 需要一点时间

线程同步:

 多个线程操作同一个资源

并发:

java里面的多线程_第26张图片

java里面的多线程_第27张图片

java里面的多线程_第28张图片

三大不安全例子: 

不安全的买票:

//线程不安全 有重复的票被买到不同人手里面

public class UnsafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket buyTicket = new BuyTicket();

        new Thread(buyTicket, "第1个人").start();
        new Thread(buyTicket, "第2个人").start();
        new Thread(buyTicket, "第3个人").start();
    }
}

class BuyTicket implements Runnable {
    boolean flag = true;
    private int ticketNums = 10;

    @Override
    public void run() {
        while(flag) {
            buy();
        }
    }

    private void buy() {
        if(ticketNums <= 0) {
            flag = false;
            return;
        }
        try {
            Thread.sleep(100);//方法问题的错误性
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 买了第 " + ticketNums--);
    }
}

不安全的取钱:

package 线程;

public class UnsafeBank {
    public static void main(String[] args) {
        Account account = new Account(100, "FindYou.基金");
        Drawing you = new Drawing(account, 50, "你");
        Drawing him = new Drawing(account, 100, "他");

        you.start();
        him.start();

    }
}

class Account {//账户
    int monkey;
    String name;

    public Account(int monkey, String name) {
        this.monkey = monkey;
        this.name = name;
    }
}

//银行 模拟取款
class Drawing extends Thread {
    Account account;//账户
    int drawingMoney;//取多少钱
    int nowMoney;//现在手里有多少钱

    public Drawing(Account account, int drawingMoney, String name) {
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;
    }

    //取钱

    @Override
    public void run() {
        if(account.monkey - drawingMoney < 0 ) {
            System.out.println(Thread.currentThread().getName() + " 取钱的时候,钱不够了");
            return;
        }

        try {
            //放大问题
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        account.monkey -= drawingMoney;
        nowMoney += drawingMoney;//现在手里的钱

        System.out.println(account.name + "账户还剩: " + account.monkey);
        System.out.println(this.getName() + "手里的钱有: " + nowMoney);
    }
}
输出的结果是:
 java里面的多线程_第29张图片

线程不安全的集合:

public class UnsafeList {
    public static void main(String[] args) {
        Listlis = new ArrayList<>();

        for(int i = 0; i <= 1000; ++ i ) {
            new Thread(()->{
                lis.add(Thread.currentThread().getName());
            }).start();
        }
        System.out.println(lis.size());
    }
}
运行的结果:

有的别覆盖掉了(他们会同时进去)

 同步方法及同步块:

java里面的多线程_第30张图片

 同步代码的弊端:
java里面的多线程_第31张图片

同步块:
java里面的多线程_第32张图片

 安全的买票:

package 线程;
//线程不安全 有重复的票被买到不同人手里面
public class UnsafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket buyTicket = new BuyTicket();

        new Thread(buyTicket, "第1个人").start();
        new Thread(buyTicket, "第2个人").start();
        new Thread(buyTicket, "第3个人").start();
    }
}

class BuyTicket implements Runnable {
    boolean flag = true;
    private int ticketNums = 10;

    @Override
    public void run() {
        while(flag) {
            buy();
        }
    }
    //synchronized 变成了同步方法 实现了一个锁 锁的是this
    private  synchronized void buy() {
        if(ticketNums <= 0) {
            flag = false;
            return;
        }
        try {
            Thread.sleep(100);//方法问题的错误性
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 买了第 " + ticketNums--);
    }
}

安全与不安全的区别就是在买票 buy 这个方法上加上了synchronized

安全的取钱:

代码:

package 线程;

public class UnsafeBank {
    public static void main(String[] args) {
        Account account = new Account(100, "FindYou.基金");
        Drawing you = new Drawing(account, 50, "你");
        Drawing him = new Drawing(account, 100, "他");

        you.start();
        him.start();

    }
}

class Account {//账户
    int monkey;
    String name;

    public Account(int monkey, String name) {
        this.monkey = monkey;
        this.name = name;
    }
}

//银行 模拟取款
class Drawing extends Thread {
    Account account;//账户
    int drawingMoney;//取多少钱
    int nowMoney;//现在手里有多少钱

    public Drawing(Account account, int drawingMoney, String name) {
        super(name);
        this.account = account;
        this.drawingMoney = drawingMoney;
    }

    //取钱

    @Override
    public void run() {
        synchronized (account) {
            if(account.monkey - drawingMoney < 0 ) {
                System.out.println(Thread.currentThread().getName() + " 取钱的时候,钱不够了");
                return;
            }

            try {
                //放大问题
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            account.monkey -= drawingMoney;
            nowMoney += drawingMoney;//现在手里的钱

            System.out.println(account.name + "账户还剩: " + account.monkey);
            System.out.println(this.getName() + "手里的钱有: " + nowMoney);
        }
    }
}

加上了 synchronized (account){},  这里锁的就是account了

要是直接在void run()的前面加上synchronized,是不行的

以下是ai做出的回应:

代码中的synchronized关键字用于实现同步,它可以修饰方法或者代码块,以确保在同一时刻最多只有一个线程执行该段代码。

在您提供的代码中,synchronized关键字被用来修饰run方法。这里有一个问题:虽然run方法是同步的,但是每个Drawing对象都会拥有自己的锁,因为run方法是实例方法,锁定的是调用该方法的对象(在这个情况下是Drawing对象)。由于您创建了两个不同的Drawing对象(you和him),它们各自持有不同的锁,所以这两个线程仍然可以同时进入各自的run方法。

要正确地同步对Account对象的访问,您需要确保所有线程都使用同一个锁。在这种情况下,最合适的锁对象是共享资源Account对象本身。您可以通过同步一个代码块,并使用account作为锁对象来实现这一点。

 运行的结果:

死锁:

代码:

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

public class DeadLock {
    public static void main(String[] args) {
        Makeup m1 = new Makeup(0, "灰姑娘");
        Makeup m2 = new Makeup(1, "白雪公主");

        m1.start();
        m2.start();
    }
}

// 口红
class Lipstick {

}
// 镜子
class Mirror {

}

// 化妆
class Makeup extends Thread {
    // 需要的资源 注意只有一份
    static Lipstick lipstick = new Lipstick();
    static Mirror mirror = new Mirror();

    int choice; // 选择
    String name; // 使用化妆的人
    public Makeup(int choice, String name) {
        this.choice = choice;
        this.name = name;
    }
    @Override
    public void run() {
        // 化妆
        makeup();
    }
    // 化妆
    private void makeup() {
        if (choice == 0) {
            synchronized (lipstick) { // 获得口红的锁
                System.out.println(getName() + " 想获得口红的锁");
                try {
                    Thread.sleep(1000); // 增加延迟操作
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (mirror) { // 想获得镜子的锁
                    System.out.println(getName() + " 想获得镜子的锁");
                }
            }
        } else {
            synchronized (mirror) { // 获得镜子的锁
                System.out.println(getName() + " 想获得镜子的锁");
                try {
                    Thread.sleep(1000); // 增加延迟操作
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lipstick) { // 想获得口红的锁
                    System.out.println(getName() + " 想获得口红的锁");
                }
            }
        }
    }
}

运行的结果:

会一直卡着

解决的方法:

程序不同时抱着对方的锁,放在外边

java里面的多线程_第33张图片

运行的结果:
java里面的多线程_第34张图片

死锁避免的方法:
java里面的多线程_第35张图片

Lock锁:

java里面的多线程_第36张图片

代码演示:

package 线程;

import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
    public static void main(String[] args) {
        Sale sale = new Sale();
        new Thread(sale, "店铺1").start();
        new Thread(sale, "店铺2").start();
        new Thread(sale, "店铺3").start();
    }
}

class Sale implements Runnable {
     int tickets = 100;
     //定义lock锁 在排队
    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            try {
                lock.lock();//加锁
                if (tickets > 0) {//注意这里要加一下 检查
                    System.out.println(Thread.currentThread().getName() + " 正在售卖第:" + (100 - --tickets) + "张票");
                } else {
                    break;
                }
            } finally {
                //解锁
                lock.unlock();
            }
        }
    }
}

注意事项:

在使用 ReentrantLock 时,需要注意以下几点:

  • 必须调用 lock() 方法获取锁,调用 unlock() 方法释放锁;
  • 为了避免死锁,一定要在 finally 块中释放锁,这样可以确保无论代码执行是否成功,都会释放锁,避免死锁
  • 可以使用 tryLock() 方法尝试获取锁,如果获得锁则返回 true,否则返回 false。如果多个线程同时尝试获取锁,则只有一个线程能够成功获取锁;
  • 可以使用 newCondition() 方法创建一个条件对象,使用 await() 方法等待条件满足,使用 signal() 或 signalAll() 方法唤醒等待的线程。

synchronized和Lock的对比:

java里面的多线程_第37张图片

线程协作:

生产者和消费者

线程通信:
java里面的多线程_第38张图片

线程通信-分析:java里面的多线程_第39张图片

 java提供了几个方法解决线程之间的通信问题:
java里面的多线程_第40张图片

 解决方式1:

java里面的多线程_第41张图片

代码:

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

//需要 生产者 消费者 产品 缓冲区

public class TestPC {
    public static void main(String[] args) {
        SynContainer container = new SynContainer();
        new Product(container).start();
        new Consumer(container).start();
    }
}

//生产者
class Product extends Thread {
    SynContainer container;

    public Product(SynContainer container) {
        this.container = container;
    }

    @Override
    public void run() {
        for(int i = 0; i < 100; ++ i ) {
            System.out.println("生产了" + i + "只鸡");
            container.push(new Chicken(i));
        }
    }
}

//消费者
class Consumer extends Thread {
    SynContainer container;

    public Consumer(SynContainer container) {
        this.container = container;
    }

    @Override
    public void run() {
        for(int i = 0; i < 100; ++ i ) {
            System.out.println("消费了-->" + container.pop().id + "只鸡");
        }
    }
}

//产品
class Chicken {
    int id;//产品编号
    public Chicken(int id) {
        this.id = id;
    }
}

//缓冲区
class SynContainer {
    //需要容器的大小
    Chicken[] chickens = new Chicken[10];
    int cnt = 0;
    //生产者放入产品
    public synchronized void push(Chicken chicken) {
        //如果容器满了 需要等待消费者
        if(cnt == chickens.length) {
          //通知消费者消费
            //生产者等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果没满
        chickens[cnt++] = chicken;
        //可以通知消费者去吃啦
        this.notifyAll();
    }

    //消费的
    public  synchronized Chicken pop() {
        //如果容器里面没有 唤醒厨师 让他开始做饭
        if(cnt == 0) {
            //等待生产者生产 消费者等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果可以消费
        this.notifyAll();
        cnt--;
        return chickens[cnt];
    }
}

解决方式2:
  

代码: 

public class TestPC2 {
    public static void main(String[] args) {
        Tv tv = new Tv();
        new Player(tv).start();
        new Watcher(tv).start();
    }
}

class Player extends Thread{
    Tv tv;
    public Player(Tv tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            tv.play();
        }
    }
}

class Watcher extends Thread{
    Tv tv;
    public Watcher(Tv tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for(int i = 1; i <= 20; ++ i ) {
            tv.watch();
        }
    }
}

class Tv {
    boolean flag = true;
    //false 表示该观众看了
    //true 表示该演员表演了
    public synchronized void play() {//演员表演
        if(flag == false) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("表演了节目");
        this.notifyAll();
        this.flag = !this.flag;
    }

    public synchronized void watch() {
        if(flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("观看了节目");
        //通知演员表演
        this.notifyAll();
        this.flag = !this.flag;
    }
}

运行结果:
 java里面的多线程_第42张图片

 线程池:

java里面的多线程_第43张图片

 使用线程池:

java里面的多线程_第44张图片

代码:

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

public class TestPool {
    public static void main(String[] args) {
        //创建服务 创建线程池
        ExecutorService service = Executors.newFixedThreadPool(10);//里面的参数是 线程池的大小

        //把线程丢进去
        service.execute(new MyThread2());
        service.execute(new MyThread2());
        service.execute(new MyThread2());
        service.execute(new MyThread2());

        //关闭链接
        service.shutdown();
    }
}

class MyThread2 implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " --> Code change the word");
    }
}

运行结果:

java里面的多线程_第45张图片

你可能感兴趣的:(java)