miracle just wanna be better

线程池

2019-07-23
miracle

把若干用户线程添加到线程池中,由线程池来管理线程

为什么要使用线程池:

  1. 减少了创建和销毁线程的次数,每个工作线程都可以被重复使用或利用,可以并发执行多个任务
  2. 可以根据系统的承受能力,调整线程池中的工作线程数目,防止因为消耗过多的内存,而使服务器宕机(down)
    结论:java给提供了一些api方法,用于更好地管理线程,让程序员专心写线程的逻辑

先创建一个MyThread类个MyThread2类,供后面例子使用

public class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"正在执行");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class MyThread2 extends Thread{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"正在执行2");
    }
}

手动创建线程池

ThreadpoolExecutor xxx = new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler)

参数 含义  
int corePoolSize 核心线程数量  
int maximumPoolSize 最大线程数量  
long keepAliveTime 空闲的线程存活时间  
TimeUnit unit 时间单位  
BlockingQueue 阻塞队列  
RejectedExecutionHandler handler 拒绝服务助手  

简要结构图

例子

/**
 * 手动创建线程池
 */
public class TestExecutorsService {
    /**
     * 手动创建了一个线程池
     * @param args
     */
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 30L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println("线程数超过了线程池的容量,拒接执行任务-->"+r);
            }
        });
        //把线程放在线程池中并执行
        threadPoolExecutor.execute(new TestThread(1));
        threadPoolExecutor.execute(new TestThread(2));
        threadPoolExecutor.execute(new TestThread(3));
        threadPoolExecutor.execute(new TestThread(4));
        threadPoolExecutor.execute(new TestThread(5));
        threadPoolExecutor.execute(new TestThread(6));
        threadPoolExecutor.execute(new TestThread(7));
        threadPoolExecutor.execute(new TestThread(8));
        threadPoolExecutor.execute(new TestThread(9));
        threadPoolExecutor.execute(new TestThread(10));
        threadPoolExecutor.execute(new TestThread(11));
        threadPoolExecutor.execute(new TestThread(12));
        threadPoolExecutor.execute(new TestThread(13));
        threadPoolExecutor.execute(new TestThread(14));
        threadPoolExecutor.execute(new TestThread(15));
        threadPoolExecutor.execute(new TestThread(16));
        threadPoolExecutor.execute(new TestThread(17));



    }
}

/**
 * 写线程的逻辑
 */

class TestThread implements Runnable{
    private int num;
    public TestThread(int num){
        this.num = num;
    }
    @Override
    public void run() {
        System.out.println("第"+num+"号线程开始执行");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("第"+num+"号线程执行结束");
    }
}

线程池api的使用

Executors的线程工具类,此类提供了若干静态方法,这些静态方法用于生成线程池对象

Executors.newSingleThreadExecutor();

创建一个单线程的线程池,这个线程池只有一个线程在工作 即单线程执行任务,如果这个唯一的线程因为异常结束,那么就会有一个新的线程来替代它,因此,线程池保证所有的任务是按照任务的提交顺序来执行

例子

会逐个执行,每次只有一个线程在工作

public class TestExecutors_SingleThreadExcetor {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newSingleThreadExecutor();
        //创建若干线程
        MyThread mt1 = new MyThread();
        MyThread mt2 = new MyThread();
        MyThread mt3 = new MyThread();
        MyThread mt4 = new MyThread();
        MyThread mt5 = new MyThread();
        //把线程提交给线程池
        pool.execute(mt1);
        pool.execute(mt2);
        pool.execute(mt3);
        pool.execute(mt4);
        pool.execute(mt5);
        //关闭线程池
        pool.shutdown();

    }
}

Executors.newFilexedThreadPool(int nThreads);

创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小,线程池的大小一旦达到最大,就会保持不变;如果某个线程因为执行异常而结束,线程就会补充一个新的线程

###例子 下面例子两个线程2个线程运行,因为参数给的是2

public class TestExecutors_FixedThreadExcetor {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        //创建若干线程
        MyThread mt1 = new MyThread();
        MyThread mt2 = new MyThread();
        MyThread mt3 = new MyThread();
        MyThread2 mt4 = new MyThread2();
        MyThread2 mt5 = new MyThread2();
        //把线程提交给线程池
        pool.execute(mt1);
        pool.execute(mt2);
        pool.execute(mt3);
        pool.execute(mt4);
        pool.execute(mt5);
        //关闭线程池
        pool.shutdown();

    }
}

Executors.newCacheedThreadPool();

创建一个可以缓冲的线程池,如果线程池大小超过处理的任务所需要的线程,那么就会回收部分线程,当任务数目增加的时候,此线程池又可以智能的添加新的线程来处理任务,此线程池不会对线程大小做限制,线程池的大小完全依赖操作系统能够创建的最大的大小

例子

public class TestExecutors_CachedThreadExcetor {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newCachedThreadPool();
        //创建若干线程
        MyThread mt1 = new MyThread();
        MyThread mt2 = new MyThread();
        MyThread mt3 = new MyThread();
        MyThread mt4 = new MyThread();
        MyThread mt5 = new MyThread();
        //把线程提交给线程池
        pool.execute(mt1);
        pool.execute(mt2);
        pool.execute(mt3);
        pool.execute(mt4);
        pool.execute(mt5);
        //关闭线程池
        pool.shutdown();

    }
}

Executors.newScheduledThreadPool(int corePoolSize);

创建一个大小无限制的线程池,此线程池支持定时及周期性的执行任务的需求

例子

public class TestExecutors_ScheduledThreadExcetor {
    public static void main(String[] args) {
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
        pool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("计划执行run");
            }
        },2000,500, TimeUnit.MILLISECONDS);
    }
}


上一篇 网络编程socket

下一篇 jdk1.5新特性

Comments

Content