javaJSE---线程池

本文介绍了Java中线程池的重要性、工作原理,详细讲解了线程池的分类和生命周期,以及不同类型的阻塞队列,并提供了示例代码。此外,还讨论了线程池的关闭方法及其原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、为什么需要线程池

二、工作原理

三、线程池的分类

四、线程池的生命周期

五、阻塞对列

六、线程池关闭

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

一、为什么需要线程池

在实际使用中,线程是很占用系统资源的,如果对线程管理不善
很容易导致系统问题。因此,在大多数并发框架中都会使用线程
池来管理线程,使用线程池管理线程主要有如下好处:
– 1、使用线程池可以重复利用已有的线程继续执行任务,避免线程在创建和
销毁时造成的消耗
– 2、由于没有线程创建和销毁时的消耗,可以提高系统响应速度
– 3、通过线程可以对线程进行合理的管理,根据系统的承受能力调整可运行
线程数量的大小等

二、工作原理

 ▪ 线程池执行所提交的任务过程:
▪ 1、先判断线程池中核心线程池所有的线程是否都在执行任务。
如果不是,则新创建一个线程执行刚提交的任务,否则,核心线
程池中所有的线程都在执行任务,则进入第2步;
▪ 2、判断当前阻塞队列是否已满,如果未满,则将提交的任务放
置在阻塞队列中;否则,则进入第3步;
▪ 3、判断线程池中所有的线程是否都在执行任务,如果没有,则
创建一个新的线程来执行任务,否则,则交给饱和策略进行处理

三、线程池的分类

四、线程池的生命周期

▪ RUNNING :能接受新提交的任务,并且也能处理阻塞队列中的任务;
▪ SHUTDOWN:关闭状态,不再接受新提交的任务,但却可以继续处理阻塞队列中已保存的任务。
▪ STOP:不能接受新任务,也不处理队列中的任务,会中断正在处理任务的线程。
▪ TIDYING:如果所有的任务都已终止了,workerCount (有效线程数) 为0,线程池进入该状态后会调用 terminated() 方法进入TERMINATED 状态。
▪ TERMINATED:在terminated() 方法执行完后进入该状态,默认terminated()方法中什么也没有做。 

五、阻塞队列

1、ArrayBlockingQueue

1)Consumer.java

public class Consumer implements Runnable{
    private BlockingQueue<Integer> blockingQueue;

    public Consumer(BlockingQueue<Integer> blockingQueue) {
        this.blockingQueue = blockingQueue;
    }

    @Override
    public void run() {
        try {
            while (true){
                System.out.println("取出来的因素是:"+blockingQueue.take());
            }
        } catch (InterruptedException e) {
            System.out.println("消费者在等待新产品的时候被打断了!");
            e.printStackTrace();
        }
    }
}

 2)Producer.java

public class Producer implements Runnable {
    private BlockingQueue<Integer> blockingQueue;
    private static int element = 0;

    public Producer(BlockingQueue<Integer> blockingQueue) {
        this.blockingQueue = blockingQueue;
    }

    @Override
    public void run() {
        try {
            while (element < 20){
                System.out.println("将要放进去的因素是:"+element);
                blockingQueue.put(element++);
            }
        } catch (InterruptedException e) {
            System.out.println("生产者在等待空闲空间的时候被打断!");
            e.printStackTrace();
        }
        System.out.println("生产者终止了生产过程!");
    }
}

3)Mainclass.java

public class MainClass {
    public static void main(String[] args) {
        BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(3,true);
        Producer producerPut = new Producer(blockingQueue);
        Consumer consumerTake = new Consumer(blockingQueue);
//		ProducerOffer producerOffer = new ProducerOffer(blockingQueue);
        new Thread(producerPut).start();
        new Thread(consumerTake).start();
    }
}

2、DelayQueueTask.java

class DelayTask implements Delayed {
    public String name;
    public Long delayTime;
    public TimeUnit delayTimeUnit;
    public Long executeTime;//ms

    DelayTask(String name, long delayTime, TimeUnit delayTimeUnit) {
        this.name = name;
        this.delayTime = delayTime;
        this.delayTimeUnit = delayTimeUnit;
        this.executeTime = System.currentTimeMillis() + delayTimeUnit.toMillis(delayTime);
    }


    @Override
    public int compareTo(Delayed o) {
        if(this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)) {
            return 1;
        }else if(this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS)) {
            return -1;
        }
        return 0;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(executeTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }
}
public class DelayQueueTask {
    public static void main(String[] args) {
        DelayQueue<DelayTask> delayQueue = new DelayQueue<>();
        delayQueue.add(new DelayTask("1",1000L,TimeUnit.MILLISECONDS));
        delayQueue.add(new DelayTask("2",1000L,TimeUnit.MILLISECONDS));
        delayQueue.add(new DelayTask("3",1000L,TimeUnit.MILLISECONDS));
        System.out.println("delayQueue put done");
        while (!delayQueue.isEmpty()){
            try {
                DelayTask delayTask = delayQueue.take();
                System.out.println(delayTask.name + ":" + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

3、blockingqueue.priorityQueue

1)UsePriorityBlockingQueue.java

public class UsePriorityBlockingQueue {
    public static void main(String[] args) throws Exception{
        PriorityBlockingQueue<Task> q = new PriorityBlockingQueue<Task>();
        Task t1 = new Task();
        t1.setId(3);
        t1.setName("id为3");
        Task t2 = new Task();
        t2.setId(4);
        t2.setName("id为4");
        Task t3 = new Task();
        t3.setId(1);
        t3.setName("id为1");

        q.add(t1);	//3
        q.add(t2);	//4
        q.add(t3);  //1

        System.out.println("容器:" + q);
        System.out.println(q.take().getId());
        System.out.println("容器:" + q);
    }
}

2)Task.java

public class Task implements Comparable<Task> {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int compareTo(Task task) {
        return this.id > task.id ? 1 : (this.id < task.id ? -1 :0);
    }

    @Override
    public String toString() {
        return this.id + "," + this.name;
    }
}

4、callable

1)MyTask.java

public class MyTask implements Callable<String> {

    @Override
    public String call() throws Exception {
//        Thread.sleep(200);
        Random random = new Random();
        int i = random.nextInt(1000);

        return Thread.currentThread().getName() + "---" + i + "---" + "is running!";
    }
}

 2)Test.java

public class Test {
    public static void main(String[] args) {
        //创建线程池对象
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        //提交任务,返回一个future对象
        for (int i = 0 ; i < 20 ;i++){
            Future<String> future = executorService.submit(new MyTask());
            try {
                String s = future.get();
                System.out.println(s);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        //关闭资源
        executorService.shutdown();
    }
}

5、forkJoin

1)ForkJoinPoolAction.java

/**
 * 简单打印0-300的数值,用多线程实现并执行
*/
public class ForkJoinPoolAction {
    public static void main(String[] args) {
        PrintTask task = new PrintTask(0, 300);
        //创建实例,并执行分割任务
        ForkJoinPool pool = new ForkJoinPool();
        pool.submit(task);
        //线程阻塞,等待所有线程完成
        pool.awaitQuiescence(2, TimeUnit.SECONDS);
        //关闭线程池
        pool.shutdown();
    }
}

2)ForkJoinPoolTask.java

public class ForkJoinPoolTask {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        int[] arr = new int[100];
        Random random = new Random();
        int total = 0;
        //初始化一百个数组元素
        for (int i = 0,len = arr.length; i <len ; i++) {
            int temp = random.nextInt(20);
            //对数组元素赋值,并将数组元素的值添加到sum总和中
            total = (arr[i]=temp);
            System.out.println(Thread.currentThread().getName()+ "的arr[i]值:"+arr[i]+"求和:" + total);
        }
        System.out.println("初始化数组总合:"+total);
        SumTask sumTask = new SumTask(arr,0,arr.length);
        //创建一个通用池,这个是jdk1.8提供的功能
        ForkJoinPool pool = ForkJoinPool.commonPool();
        Future<Integer> future = pool.submit(sumTask);//提供分解的SumTask任务
        System.out.println("多线程执行结果:"+future.get());
        //关闭线程池
        pool.shutdown();
    }
}

3)PrintTask.java

public class PrintTask extends RecursiveAction {
    private static final int THRESHOLD = 50;//最多只能打印50个数
    private int start;
    private int end;

    PrintTask(int start, int end){
        super();
        this.start = start;
        this.end = end;
    }

    @Override
    protected void compute() {
        if(end - start < THRESHOLD){
            for (int i = start; i <end ; i++) {
                System.out.println(Thread.currentThread().getName()+"----i的值"+i);
            }
        }else {
            int middle =(start + end)/2;
            PrintTask left = new PrintTask(start,middle);
            PrintTask right = new PrintTask(middle,end);
            //并行执行两个小任务
            left.fork();
            right.fork();
        }
    }
}

4)SumTask.java

public class SumTask extends RecursiveTask<Integer> {
    private static final int THRESHOLD = 20;//每个小任务,最多只累加20个数
    private int array[];
    private int start;
    private int end;

    /**
     * Creates a new instance of SumTask.
     * 累加从start到end的array数组
     * array
     * start
     * end
     */

    public SumTask(int[] array, int start, int end) {
        super();
        this.array = array;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        int sum = 0;
        //当end与start之间的差小于threshold时,开始进行实际的累加
        if(end - start <THRESHOLD){
            for (int i = start; i <end ; i++) {
                sum += array[i];
                System.out.println(Thread.currentThread().getName()+"i的值:"+array[i]+",求和:"+sum);
            }
            return sum;
        }else {//当end与start之间的差大于threshold,即要累加的数超过20个时候,将大任务分解成小任务
            int middle = (start + end)/2;
            SumTask left = new SumTask(array,start,middle);
            SumTask right = new SumTask(array,middle,end);
            //并行执行两个小任务
            left.fork();
            right.fork();
            //把两个小任务累加的结果合并起来
            return left.join() + right.join();
        }
    }
}

6、thread_Pool.java

1)CachedThreadPoolDemo.java

public class CachedThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        //提交任务
        for (int i = 0; i <20 ; i++) {
            executorService.execute(new MyTask());
        }
        //关闭线程池
        executorService.shutdown();
    }
}

2)FixedThreadPoolDemo.java

public class FixedThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for (int i = 0; i <20 ; i++) {
            executorService.execute(new MyTask());
        }
        executorService.shutdown();
    }
}

3)MyTask.java

public class MyTask implements Runnable{
    @Override
    public void run() {
//        try {
//            Thread.sleep(200);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        System.out.println(Thread.currentThread().getName() + "----is running");
    }
}

4)SingleThreadExecutorDemo.java

public class SingleThreadExecutorDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i <30 ; i++) {
            executorService.execute(new MyTask());
        }
        executorService.shutdown();
    }
}

7、ThreadPoolExecutorDemo。javaliu

public class ThreadPoolExecutorDemo {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,11,60L, TimeUnit.SECONDS,new ArrayBlockingQueue(5));
        for (int i = 0; i < 20; i++) {
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " is running! ");
                }
            });
        }
        threadPoolExecutor.shutdown();
    }
}

六、线程池关闭

 ▪ 关闭线程池,可以通过shutdown和shutdownNow两个方法
▪ 原理:遍历线程池中的所有线程,然后依次中断
▪ 1、shutdownNow首先将线程池的状态设置为STOP,然后尝试停止所有的正在执行和未执行任务的线程,并返回等待执行任务的列表;
▪ 2、shutdown只是将线程池的状态设置为SHUTDOWN状态,然后中断所有没有正在执行任务的线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值