多线程_传送带我们到底能走多远系列(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();
                    }
                }
            }
        }
    }
}

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

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

原文地址:https://www.cnblogs.com/killbug/p/2677506.html