多线程任务类型-CPU/I/O-XXOO

一、多线程任务类型

多线程任务类型分为CPU 密集型以及I/O 密集型任务

CPU 密集型

* 这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU 核心数)+1,

* 比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其它原因导致的任务暂停而带来的影响。

* 一旦任务暂停,CPU 就会处于空闲状态,而在这种情况下多出来的一个线程就可以充分利用 CPU 的空闲时间。

I/O 密集型任务

* 这种任务应用起来,系统会用大部分的时间来处理 I/O 交互,而线程在处理 I/O 的时间段内

* 不会占用 CPU 来处理,这时就可以将 CPU 交出给其它线程使用。因此在 I/O 密集型任务的应用中,

* 我们可以多配置一些线程,具体的计算方法是 2N。

二、代码示例

1.CPU 密集型

package com.yl.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Vector;

/**
 * 多线程任务类型CPU 密集型
 * 这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU 核心数)+1,
 * 比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其它原因导致的任务暂停而带来的影响。
 * 一旦任务暂停,CPU 就会处于空闲状态,而在这种情况下多出来的一个线程就可以充分利用 CPU 的空闲时间。
 * @author toshiba
 * @date 2020/5/25
 */
@Component
@Slf4j
public class CpuTypeThread implements Runnable{

    /**
     * 线程名称
     */
    int threadNext = 0;

    /**
     * 整体执行时间,包括在队列中等待的时间
     */
    List<Long> wholeTimeList;

    /**
     * 真正执行时间
     */
    List<Long> runTimeList;


    private long initStartTime = 0;


    /**

     * 构造函数

     * @param runTimeList

     * @param wholeTimeList

     */

    public CpuTypeThread(List<Long> runTimeList, List<Long> wholeTimeList, int threadNext) {

        initStartTime = System.currentTimeMillis();

        this.runTimeList = runTimeList;

        this.wholeTimeList = wholeTimeList;

        this.threadNext = threadNext;

    }


    /**

     * 判断素数

     * @param number

     * @return

     */

    public boolean isPrime(final int number) {

        if (number <= 1) {
            return false;
        }


        for (int i = 2; i <= Math.sqrt(number); i++) {

            if (number % i == 0) {
                return false;

            }

        }

        return true;

    }


    /**
     * 計算素数
     * @param lower
     * @param upper
     * @return
     */
    public int countPrimes(final int lower, final int upper) {

        int total = 0;

        for (int i = lower; i <= upper; i++) {

            if (isPrime(i)) {
                total++;
            }

        }

        return total;

    }


    @Override
    public void run() {

        long start = System.currentTimeMillis();

        countPrimes(1, 1000000);

        long end = System.currentTimeMillis();



        long wholeTime = end - initStartTime;

        long runTime = end - start;

        wholeTimeList.add(wholeTime);

        runTimeList.add(runTime);

        log.info(" CpuTypeThread-"+threadNext+"-- 单个线程花费时间:" + (end - start));

    }
}


2.I/O 密集型任务

package com.yl.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Vector;

/**
 * I/O 密集型任务
 * 这种任务应用起来,系统会用大部分的时间来处理 I/O 交互,而线程在处理 I/O 的时间段内
 * 不会占用 CPU 来处理,这时就可以将 CPU 交出给其它线程使用。因此在 I/O 密集型任务的应用中,
 * 我们可以多配置一些线程,具体的计算方法是 2N。
 * @author toshiba
 * @date 2020/5/25
 */
@Component
@Slf4j
public class IoTypeThread implements Runnable{

    /**
     * 线程名称
     */
    int threadNext = 0;

    /**
     * 整体执行时间,包括在队列中等待的时间
     */
    Vector<Long> wholeTimeList;

    /**
     * 真正执行时间
     */
    Vector<Long> runTimeList;


    private long initStartTime = 0;


    /**

     * 构造函数

     * @param runTimeList

     * @param wholeTimeList

     */

    public IoTypeThread(Vector<Long> runTimeList, Vector<Long> wholeTimeList, int threadNext) {

        initStartTime = System.currentTimeMillis();

        this.runTimeList = runTimeList;

        this.wholeTimeList = wholeTimeList;

        this.threadNext = threadNext;

    }


    /**
     * IO 操作
     * @throws IOException
     */
    public void readAndWrite() throws IOException {

        File sourceFile = new File("D:/YlDream/path.txt");

        // 创建输入流

        BufferedReader input = new BufferedReader(new FileReader(sourceFile));

        // 读取源文件, 写入到新的文件

        String line = null;

        while((line = input.readLine()) != null){


        }

        // 关闭输入输出流

        input.close();

    }


    @Override
    public void run() {

        long start = System.currentTimeMillis();

        try {

            readAndWrite();

        } catch (IOException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

        long end = System.currentTimeMillis();



        long wholeTime = end - initStartTime;

        long runTime = end - start;

        wholeTimeList.add(wholeTime);

        runTimeList.add(runTime);

        log.info(" IoTypeThread-"+threadNext+"-- 单个线程花费时间:" + (end - start));

    }

}

测试

package com.yl.test;

import com.yl.util.CpuTypeThread;
import com.yl.util.IoTypeThread;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.*;


/**
 * 线程池定义
 * @author toshiba
 * @date 2020/5/25
 */
@Slf4j
public class ThreadTest {

    /**
     * 核心池的大小
     */
    private final static int corePoolSize = 5;

    /**
     * 线程池最大线程数
     */
    private final static int maximumPoolSize = 10;

    /**
     * 线程没有任务执行时最多保持多久时间会终止
     */
    private final static long  keepAliveTime = 100;

    /**
     * 参数keepAliveTime的时间单位,有7种取值
     * TimeUnit.DAYS;               //天
     * TimeUnit.HOURS;             //小时
     * TimeUnit.MINUTES;           //分钟
     * TimeUnit.SECONDS;           //秒
     * TimeUnit.MILLISECONDS;      //毫秒
     * TimeUnit.MICROSECONDS;      //微妙
     * TimeUnit.NANOSECONDS;       //纳秒
     */
    private final static TimeUnit unit = TimeUnit.SECONDS;


    /**
     * 一个阻塞队列,用来存储等待执行的任务,这个参数的选择也很重要,会对线程池的运行过程产生重大影响
     * ArrayBlockingQueue;
     * LinkedBlockingQueue;
     * SynchronousQueue;
     * ArrayBlockingQueue和PriorityBlockingQueue使用较少,一般使用LinkedBlockingQueue
     * 和Synchronous。线程池的排队策略与BlockingQueue有关。
     */
    private final static BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue();



    /**
     * 线程工厂,主要用来创建线程
     */
    private final static ThreadFactory threadFactory = null;



    /**
     * 表示当拒绝处理任务时的策略,有以下四种取值:
     * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
     * ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
     * ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
     * ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
     */
    private final static RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();


    public static void main(String[] args) {

        ThreadPoolExecutor  executor = new ThreadPoolExecutor(
                corePoolSize, maximumPoolSize, keepAliveTime,
                unit, workQueue, handler);

        CpuTypeThread thread;
        IoTypeThread threadI;

        List<Long> runTimeList = new ArrayList<>();
        List<Long> wholeTimeList = new ArrayList<>();

        Vector<Long> runTimeListV = new Vector<>();
        Vector<Long> wholeTimeListV = new Vector<>();

        for(int i = 0; i < 150; i++){
            thread = new CpuTypeThread(runTimeList, wholeTimeList, i);
            executor.execute(thread);
            log.info("thread-线程池中线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数目:"+
                    executor.getQueue().size()+",已执行完的任务数目:"+executor.getCompletedTaskCount());
            threadI = new IoTypeThread(runTimeListV, wholeTimeListV, i);
            executor.execute(threadI);
            log.info("threadI-线程池中线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数目:"+
                    executor.getQueue().size()+",已执行完的任务数目:"+executor.getCompletedTaskCount());
        }
        executor.shutdown();

    }
}

以上

Guess you like

Origin blog.csdn.net/qq_35731570/article/details/109722873