• Java多线程04


    生产者&消费者

    这是个线程同步问题, 生产者和消费者共享同一个资源, 并且两者之间互相依赖, 互为条件

    • 对于生产者, 没有生产产品之前, 要通知消费者等待. 生产了产品后, 又需要马上通知消费者消费
    • 对于消费者, 在消费之后要通知生产者已经结束消费, 需要生产新的产品
    • 仅有 syn 是不够的
      • syn 可阻止并发更新同一个共享资源, 实现同步
      • syn 不能用来实现不同线程之间的消息传递
    • 方法
      • wait() 表示线程一直等待, 直到其他线程通知, 与sleep不同, 会释放锁
      • notify() 唤醒一个处于等待状态的线程
        注意 : 均是Object类的方法, 都只能在同步方法或同步代码块中使用, 否则会抛出异常 IIIegalMonitorStateException

    解决方式一

    生产者 -- 缓冲区 -- 消费者

    package com.guanxing.PC;
    
    import javax.swing.plaf.IconUIResource;
    
    //测试生产者&消费者模型-->利用缓冲区解决:管程法
    //生产者 消费者 产品 缓冲区
    public class TestPC {
        public static void main(String[] args) {
            SynContainer container = new SynContainer();
    
            new Productor(container).start();
            new Consumer(container).start();
        }
    }
    
    //生产者
    class Productor extends Thread {
        SynContainer container;
    
        public Productor(SynContainer container) {
            this.container = container;
        }
    
        //生产
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                container.push(new Chicken(i), 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 count = 0;
    
        //生产者放入产品
        public synchronized void push(Chicken chicken, int i) {
            //如果容器满了,就需要等待消费者消费
            if (count==chickens.length) {
                //通知消费者消费,生产等待
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //没有满,就需要丢入产品
            chickens[count]=chicken;
            count++;
            System.out.println("生产了"+i+"只鸡");
            //可以通知消费者消费了
            this.notifyAll();
        }
    
        //消费者消费产品
        public synchronized Chicken pop() {
            //判断能否消费
            if (count==0) {
                //没有产品,等待生产者生产
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //如果可以消费
            count--;
            Chicken chicken = chickens[count];
    
            //吃完了,通知生产者生产
            this.notifyAll();
            return chicken;
        }
    }
    

    解决方式二

    信号灯法

    package com.guanxing.PC;
    
    //信号灯法
    public class TestPC2 {
        public static void main(String[] args) {
            TV tv = new TV();
    
            new Actor(tv).start();
            new Watcher(tv).start();
        }
    }
    
    //定义演员 --> 生产者
    class Actor extends Thread{
        TV tv;
        public Actor(TV tv) {
            this.tv = tv;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                if (i%2==0) {
                    tv.play("你画我猜"+i);
                }else {
                    tv.play("外来媳妇本地郎"+i);
                }
            }
        }
    }
    
    //定义观众 --> 消费者
    class Watcher extends Thread{
        TV tv;
        public Watcher(TV tv) {
            this.tv = tv;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                tv.watch();
            }
        }
    }
    
    //定义产品 --> tv
    class TV {
        //演员表演,观众等待 T
        //观众观看,演员等待 F
        String show;
        boolean flag = true;
    
        //表演
        public synchronized void play(String show) {
            if (!flag) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("演员表演了"+show);
            //通知观众观看
            this.notifyAll();
            this.show = show;
            this.flag = !flag;
        }
        //观看
        public synchronized void watch() {
            if (flag) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("观众观看了"+show);
            //通知演员表演
            this.notifyAll();
            this.flag = !flag;
        }
    }
    

    线程池

    package com.guanxing.syn;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    //测试线程池
    public class TestPool {
        public static void main(String[] args) {
            //1.创建服务,创建线程池
            ExecutorService service = Executors.newFixedThreadPool(3);
    
            //2.执行
            service.execute(new MyThread());
            service.execute(new MyThread());
            service.execute(new MyThread());
            service.execute(new MyThread());
    
            //3.关闭服务
            service.shutdown();
        }
    }
    
    class MyThread implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }
    

    多线程总结

    package com.guanxing.adv;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    //回顾总结线程的创建
    public class ThreadNote{
        public static void main(String[] args) {
            //1.第一种启动方式
            new MyThread1().start();
    
            //2.第二种,需要代理类
            new Thread(new MyThread2()).start();
    
            //3.第三种
            FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyThread3());
            new Thread(futureTask).start();
            try {
                Integer integer = futureTask.get();
                System.out.println(integer);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    
    //1.继承Thread类
    class MyThread1 extends Thread{
        @Override
        public void run() {
            System.out.println("MyThread1");
        }
    }
    
    //2.实现Runnable接口
    class MyThread2 implements Runnable{
        @Override
        public void run() {
            System.out.println("MyThread2");
        }
    }
    
    //3.实现Callable接口
    class MyThread3 implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            System.out.println("MyThread3");
            return 100;
        }
    }
    
  • 相关阅读:
    大学生程序猿IT情书“2014爱的告白挑战赛”获奖名单及优秀情书展示系列之
    HDU 4952 Poor Mitsui(贪心)
    linux-CentOS6.4安装Memcached+memcached扩展+安装memcache扩展+Memcache+mecached同步SESSION的几种方法
    POJ 1006 Biorhythms(中国剩余定理 )
    java多线程实验 滚动字
    学习鸟哥的Linux私房菜笔记(17)——Linux引导流程
    PCI的imagework已由freeview软件代替
    小强的HTML5移动开发之路(26)—— JavaScript回顾1
    小强的HTML5移动开发之路(25)—— AppCan开发环境
    小强的HTML5移动开发之路(24)—— PhoneGap Android开发环境搭建
  • 原文地址:https://www.cnblogs.com/straightup/p/14503486.html
Copyright © 2020-2023  润新知