• 多线程_传送带我们到底能走多远系列(6)


    我们到底能走多远系列(6)

      光阴似箭,我居然也到了需要相亲的年龄。

      我已经开始准备向人生成熟的阶段前进,就像一个苹果,从青苹果到成熟,要经历很多,要面对很多,这一路,每一位在我身边的朋友都有你的功劳。

       加油,各位,我们都不孤单。

      ----------------------------------------------------------------

    java多线程的一些理解:
    关于同步方法,我们不得不需要记住:
    1,线程在一个对象上,两个线程不可以调用两个不同的同步方法
    2,当一个同步方法已经执行,其他线程还是能够调用这个对象的非同步方法。

      selvlet中为了提高响应速度,采用的是在初始化时将一个servlet实例化后放到一个Map中,当需要响应时直接从这个Map中取出实例用就可以了,如此即可提高反复同时调用同个servlet时的响应时间。
      而servlet本身多线程的,在对于同一个servlet的调用时,采用的是线程池的方式。(关于线程池,对于tomcat,可以再server.xm中通过<connector>元素在设定线程池中的数目)
      所以,玩servlet的都应该明白:servlet是线程非安全的。

    网上推荐的避免非安全的方式:
    1,使用SingleThread,现在的servlet版本中已经被废弃,可以无视。
    2,同步共享数据的操作,在所有的多线程中多用得到。
    3,不要使用实例变量,静态变量

    静态变量是线程非安全的
    实例变量单例模式时是线程非安全的
    局部变量是线程安全的
    

     ----------------------------------------

    多线程控制的精髓应该是控制共享数据从而控制多线程逻辑。

    两个线程轮流执行任务:

    主程序:

    public class MainTest {
    
        public static void main(String[] args) {
            FlgClass flgClass = new FlgClass();//共享数据
            //两个线程
            Thread t1 = new Thread(new Thread1(flgClass));
            Thread t2 = new Thread(new Thread2(flgClass));
            t1.start();
            t2.start();
        }
    }

    共享数据类:

    //共享数据
    public class FlgClass {
        
        private boolean flg;
    
        public boolean isFlg() {
            return flg;
        }
    
        public void setFlg(boolean flg) {
            this.flg = flg;
        }
    
    }

    两个线程:

    public class Thread1 implements Runnable {
    
        private FlgClass flgClass;
    
        Thread1(FlgClass flgClass) {
            this.flgClass = flgClass;
        }
    
        public void run() {
            int i = 5;
            synchronized (flgClass) {
                // 在一个循环中
                while (i > 0)
                    if (flgClass.isFlg()) {
                        System.out.println(Thread.currentThread().getName() + " "
                                + i);
                        flgClass.setFlg(false);//控制共享数据从而控制线程逻辑
                        flgClass.notify();
                        --i;
                    } else {
                        try {
                            flgClass.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
            }
        }
    }
    public class Thread2 implements Runnable {
        private FlgClass flgClass;
    
        Thread2(FlgClass flgClass) {
            this.flgClass = flgClass;
        }
    
        public void run() {
            int i = 5;
            synchronized (flgClass) {
    
                while (i > 0)
                    if (!flgClass.isFlg()) {
                        System.out.println(Thread.currentThread().getName() + " "
                                + i);
                        flgClass.setFlg(true);
                        flgClass.notify();
                        --i;
                    } else {
                        try {
                            flgClass.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
            }
        }
    }

    关于线程池:

    //创建一个可重用固定线程数的线程池
      ExecutorService pool = Executors.newFixedThreadPool(2);
    //创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
      ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
    //创建等待队列
      BlockingQueue bqueue = new ArrayBlockingQueue(20);
      //创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。
      ThreadPoolExecutor pool = new ThreadPoolExecutor(2,3,2,TimeUnit.MILLISECONDS,bqueue);

    分工使现代社会进步!

    做一个产品现在都是分工到很细,一个工人只要做好一件事就可以了,比如制造手机,一批工人只做手机屏幕,一批工人做外壳等等这样分工后,提高了生产效率。

    我想到传送带上的工作流程:一个工人焊接一个点后,产品就会传下去,下一个工人焊接另一个点,知道最后一个工人拿到的是成品只需要包装一下。

    和前辈聊天的时候,他说像网络交互这种程序大多是这样工作的。

    所以我想学习下,一个简单的流程模型

    实现:

    产品类:

    /**
     * 
     * 简化的产品类 作为共享数据,是线程逻辑的操作对象
     */
    public class Product {
    
        // 产品编号
        private int id;
        // 用state来查看产品处在什么阶段
        private int state;
        
        Product(int id, int state){
            this.id = id;
            this.state = state;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public int getState() {
            return state;
        }
    
        public void setState(int state) {
            this.state = state;
        }
    }

    主函数:

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class PoolTest {
    
        public static void main(String[] args) {
            // 创建一个可重用固定线程数的线程池(生产者线程池)
            ExecutorService producerPool = Executors.newFixedThreadPool(3);
            // 包装工人线程池(就是有3个包装工人嘛)
            ExecutorService packerPool = Executors.newFixedThreadPool(3);
            
            // 有5分产品需要操作
            Product p1 = new Product(1, 1);
            Product p2 = new Product(2, 1);
            Product p3 = new Product(3, 1);
            Product p4 = new Product(4, 1);
            Product p5 = new Product(5, 1);
            
            // 需要5个生产工人的活
            producerPool.execute(new Producer(p1));
            producerPool.execute(new Producer(p2));
            producerPool.execute(new Producer(p3));
            producerPool.execute(new Producer(p4));
            producerPool.execute(new Producer(p5));
            
            // 需要5个包装工人的活
            packerPool.execute(new Packer(p1));
            packerPool.execute(new Packer(p2));
            packerPool.execute(new Packer(p3));
            packerPool.execute(new Packer(p4));
            packerPool.execute(new Packer(p5));
    
            // 关闭线程池
            producerPool.shutdown();// 我想在shutdown的时候应该要检查这个pool里的线程都释放了吧
            packerPool.shutdown();
        }
    }

    生产线程:

    public class Producer extends Thread {
    
        private Product product;
    
        Producer(Product product) {
            this.product = product;
        }
    
        @Override
        public void run() {
            synchronized (product) {
                while (true) {
                    if (product.getState() == 1) {
                        System.out.println(product.getId() + "号---进入生产阶段---");
                        try {
                            product.setState(2);// 标记下一个阶段
                            sleep(500);
                            System.out.println(product.getId() + "号---生产完毕---");
                            product.notify();// 释放资源,相当于把生产好的产品传送给下一个操作者-->包装
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else if(product.getState() > 1){// 已经进入下一个阶段
                        break;// 释放线程
                    }else{// 在生产阶段之前
                        try {
                            product.wait(); // 产品还不能进入生产阶段
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    包装线程:

    public class Packer extends Thread{
        
        private Product product;
    
        Packer(Product product) {
            this.product = product;
        }
        
        @Override
        public void run() {
            synchronized (product) {
                while (true) {
                    if (product.getState() == 2) {
                        System.out.println(product.getId() + "号---进入包装阶段---");
                        try {
                            product.setState(3);// 标记下一个阶段
                            sleep(100);
                            System.out.println(product.getId() + "号---包装完毕---");
                            product.notify();// 释放资源,相当于把包装好的产品传送给下一个阶段
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else if(product.getState() > 2){// 已经进入下一个阶段
                        break;// 释放线程
                    }else{// 在包装阶段之前
                        try {
                            product.wait(); // 产品还不能进入包装阶段
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    ----------------------------------------------------------------------

    努力不一定成功,但不努力肯定不会成功。
    共勉。

  • 相关阅读:
    7zip 自解压安装程序
    修改当前启动菜单项的HyperVisorLaunchType
    VMware 虚拟镜像转 Hyper-V(Win10/2016)
    旋转基础知识
    变换及移动基础知识
    文字及排版章末小结
    文字排版相关
    文字变形及封套扭曲
    LinQ学习笔记.
    PHP笔记-PHP中Web Service.
  • 原文地址:https://www.cnblogs.com/killbug/p/2677506.html
Copyright © 2020-2023  润新知