Java多线程任务和阻塞队列实现生产者消费者封装

1.多线程任务

使用线程池执行多线程任务

我们使用多线程做一些业务操作时主要有自己继承Thread类,或者实现Runable接口实现,但是自己创建线程都不利于线程的管理和回收,这个时候我们就考虑使用线程池了,我们常用创建线程池的方式是通过Executors类的new...Pool()方法创建线程池,笔者开始也是这样(笔者使用的是IDEA,安装了阿里的代码规范)但是在newFixedThreadPool()时阿里规范提示最好自己创建线程

ExecutorService service = Executors.newFixedThreadPool();

Java多线程任务和阻塞队列实现生产者消费者封装_第1张图片

 于是看了下newFixedThreadPool()方法其实是new ThreadPoolExecutor(),将参数给死了队列的长度没有给定

Java多线程任务和阻塞队列实现生产者消费者封装_第2张图片

继续看LinkedBlockingQueue的这个构造方法长度是正数的最大值,所以阿里代码规约说会报OOM

Java多线程任务和阻塞队列实现生产者消费者封装_第3张图片

修改代码

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-call-runner-%d").build();
        ThreadPoolExecutor pool = new ThreadPoolExecutor(consumerThread, consumerThread,
                0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), namedThreadFactory);

使用CountDownLatch控制线程执行退出

为了解决子线程执行完所有任务后线程假死状态,同时为了控制主线程在子线程执行时是等待主线程执行,还是退出我们使用CountDownLatch,当一个线程完成了自己的任务后,计数器的值减1。当计数器值到达0时,它表示所有的线程已经完成了任务这个时候主线程使用latch.await()就可以控制主线程是否继续执行

最终封装代码

package com.smart.utils.consumerservice;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: jj
 * @Date: 2019/5/9 16:17
 * @Version 1.0
 */
public abstract class ConsumerService {
    private AtomicInteger c;
    private Integer consumerThread = 1;
    private boolean isAsynchronous = false;

    public ConsumerService(Integer c) {
        this.c = new AtomicInteger(c);
    }

    public Integer getConsumerThread() {
        return consumerThread;
    }

    public void setConsumerThread(Integer consumerThread) {
        this.consumerThread = consumerThread;
    }

    public boolean isAsynchronous() {
        return isAsynchronous;
    }

    public void setAsynchronous(boolean asynchronous) {
        isAsynchronous = asynchronous;
    }

    public abstract void consumer();

    public void start() throws Exception{

        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-call-runner-%d").build();
        ThreadPoolExecutor pool = new ThreadPoolExecutor(consumerThread, consumerThread,
                0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), namedThreadFactory);
        CountDownLatch latch = new CountDownLatch(consumerThread);

        for (int i = 0; i < consumerThread; i++) {
            pool.execute(
                    () -> {
                        try {
                            while (c.get() > 0) {
                                c.getAndDecrement();
                                consumer();
                            }
                        } catch (Exception e) {
                            throw e;
                        } finally {
                            latch.countDown();
                        }
                    }
            );
        }
        try {
            if (!isAsynchronous){
                latch.await();
            }
            pool.shutdown();
        } catch (Exception e) {
            throw e;
        }
    }
}

代码中的c需要执行的任务数量,consumerThread表示需要多少个线程去执行,isAsynchronous是同步等待子线程执行完还是异步执行写个main方法测试

public static void main(String[] args) {
        try {
            ConsumerService service = new ConsumerService(10) {
                @Override
                public void consumer() {
                    try {
                        Thread.sleep(200);
                        System.out.println(Thread.currentThread().getName()+":执行一个任务");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            service.setConsumerThread(6);
            service.setAsynchronous(false);
            service.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("主线程执行。。。。。。");
    }

Java多线程任务和阻塞队列实现生产者消费者封装_第4张图片

现在试试异步执行

结果

Java多线程任务和阻塞队列实现生产者消费者封装_第5张图片

2.生产者消费者

生产者消费者就是在其上多加一个生产者

package com.smart.utils.consumerservice;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: jj
 * @Date: 2019/5/9 14:31
 * @Version 1.0
 */
public abstract class ProviderConsumer {

    private AtomicInteger p;
    private AtomicInteger c;
    private Integer providerThread = 1;
    private Integer consumerThread = 1;

    public Integer getProviderThread() {
        return providerThread;
    }

    public void setProviderThread(Integer providerThread) {
        this.providerThread = providerThread;
    }

    public Integer getConsumerThread() {
        return consumerThread;
    }

    public void setConsumerThread(Integer consumerThread) {
        this.consumerThread = consumerThread;
    }

    public ProviderConsumer(Integer size) {
        p = new AtomicInteger(size);
        c = new AtomicInteger(size);
    }

    public abstract void provider();

    public abstract void consumer();

    public void start() throws Exception{
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-call-runner-%d").build();
        int sise = providerThread + consumerThread;
        ThreadPoolExecutor pool = new ThreadPoolExecutor(sise, sise,
                0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), namedThreadFactory);
        CountDownLatch latch = new CountDownLatch(sise);

        for (int i = 0; i < providerThread; i++) {
            pool.execute(
                    () -> {
                        try {
                            while (p.get() > 0) {
                                provider();
                                p.getAndDecrement();
                            }
                        } catch (Exception e) {
                            throw e;
                        } finally {
                            latch.countDown();
                        }
                    }
            );
        }
        for (int i = 0; i < consumerThread; i++) {
            pool.execute(
                    () -> {
                        try {
                            while (c.get() > 0) {
                                c.getAndDecrement();
                                consumer();
                            }
                        } catch (Exception e) {
                            throw e;
                        } finally {
                            latch.countDown();
                        }
                    }
            );
        }
        try {
            pool.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

碍于篇幅直接贴代码下次在分析吧,第一次发博客,哪里有错还望指正

你可能感兴趣的:(Java多线程)