Java线程池中哪些事??

简介: Java线程池中哪些事??

需要提前把线程准备好!!创建线程不是直接从系统申请,而是从池子里拿!

等到线程不用了,也是还给池子!!

池子的目的是为了提高效率

线程的创建虽然比进程轻量,但是在频繁创建的情况下,开销也是不可忽略的!!则希望还能进一步提高效率,那么,就需要用到线程池了!!

为啥从池子里拿线程比从系统创建线程更高效??

原因:从线程池那线程,存粹的用户态操作,从系统创建线程,涉及到用户态和内核态之间的切换,真正的创建,是要在内核态完成的~~

纯用户态操作时间是可控的!

涉及到内核态操作,时间就不太可控了!

标准库里提供了现成的线程池~~

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
    public static void main(String[] args) {
        ExecutorService pool= Executors.newFixedThreadPool(10);
        //此处并非直接new ExecutorService 对象,而是通过Executors类,里面的静态方法,完成对象的构造
        //工厂模式:创建对象不在new,而是使用一些其他的方法(通常为静态方法),协助我们把对象创建出来
        //Executors.newFixedThreadPool(10)构造一个固定为10线程的线程池
        //Executors.newFixedThreadPool()不设置固定值,按需创建,用完了不会立即销毁,留着以后接着用!
        pool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });
    }
}

需要大家主注意一下笔者的这些备注~

上述的这些工厂方法,其实都是基于一个类:ThreadPoolExecutor的封装(参数很多,还挺抽象的)

总分:多线程代码,还是挺复杂的,稍微不留点神额,就会有问题!

但是,在Java圈子里,多线程仍然是一个比较主流的并发编程模型~

线程池:从线程池取线程,是属于纯用户态操作,不涉及到和内存的交互!!

ThreadPoolExecutor:标准库提供的四种拒绝策略

ThreadPoolExecutor.AbortPolicy:如果满了,继续添加任务,添加操作直接抛出异常

ThreadPoolExecutor.CallerRunsPolicy:添加的线程自己负责执行这个任务

ThreadPoolExecutor.DiscardOldestPolicy:丢弃最老的任务(最先安排的任务)

ThreadPoolExecutor.DiscardPolicy:丢弃最新的任务

接下来,我们来自己实现一个线程池:

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
class MyThreadPool {
    //手动实现一个线程池
    //阻塞队列
    private BlockingDeque<Runnable> queue=new LinkedBlockingDeque<>();
    public void submit(Runnable runnable) throws InterruptedException{
        queue.put(runnable);
    }
    //此处实现一个固定线程数的线程池
    public MyThreadPool(int n){//n表示线程数量
        for (int i = 0; i < n; i++) {
            Thread t=new Thread(()->{
                try {
                    while (true){
                        //while可确保不停的取任务
                        Runnable runnable=queue.take();
                        runnable.run();
                    }
                }catch (InterruptedException o){
                    o.printStackTrace();
                }
            });
            //启动线程
            t.start();
        }
    }
}
public class Main1 {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool pool=new MyThreadPool(10);//创建线程池
        for (int i = 0; i < 100; i++) {
            int number=i;
            //匿名内部类,而lambad本质就是匿名内部类的简化写法!!
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello + main");
                }
            });
        }
        Thread.sleep(1000);
    }
}

根据代码的运行结果:

可以看到:线程池中任务执行的顺序和添加顺序不一定相同!!非常正常!!原因:创建的这10个线程是无序调度的!

问题1:

在上述的代码中:用到了number=i;直接用不行吗??

每次循环都是创建新的number,没有人修改该number,匿名内部类也是要捕获外界变量,而变量捕获要求得是final,而此处的 i 在跟着for循环在不停的修改,因此,创建一个新的变量,让起每次for循环都变成新的!!

问题2:

当前代码中,搞了个10个线程的线程池,在实际开发中,一个线程池的线程数量设置多少是比较合适的??

肯定线程并不是越多越好!!线程的执行本质上是要在CPU上调度的(资源)!最好的做法是做测试的方式来确定!(运行下程序,计算下时间,同时监测资源使用状态)

到此为止:多线程大致结束!!

多线程初阶,主要介绍了线程的概念,及其多线程编程,多线程编程的注意事项,代码案列,算是最核心的部分了!!

面试常考+工作常用!!

多线程进阶(锦上添花),学有余力可以搞搞!!(能理解最好,不能理解就背)

主要围绕一些更深奥的面试题来展开的!

相关文章
|
5天前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
5天前
|
存储 监控 安全
一天十道Java面试题----第三天(对线程安全的理解------>线程池中阻塞队列的作用)
这篇文章是Java面试第三天的笔记,讨论了线程安全、Thread与Runnable的区别、守护线程、ThreadLocal原理及内存泄漏问题、并发并行串行的概念、并发三大特性、线程池的使用原因和解释、线程池处理流程,以及线程池中阻塞队列的作用和设计考虑。
|
6天前
|
缓存 监控 Java
Java性能优化:从单线程执行到线程池管理的进阶实践
在Java开发中,随着应用规模的不断扩大和用户量的持续增长,性能优化成为了一个不可忽视的重要课题。特别是在处理大量并发请求或执行耗时任务时,单线程执行模式往往难以满足需求,这时线程池的概念便应运而生。本文将从应用场景举例出发,探讨Java线程池的使用,并通过具体案例和核心代码展示其在实际问题解决中的强大作用。
20 1
|
11天前
|
安全 算法 Java
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)(下)
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)
47 6
|
11天前
|
存储 安全 Java
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)(中)
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)
51 5
|
7天前
|
Java
Java线程池核心数为0时,线程池如何执行?
【8月更文挑战第11天】Java线程池核心数为0时,线程池如何执行?
21 1
|
11天前
|
存储 安全 Java
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)(上)
17 Java多线程(线程创建+线程状态+线程安全+死锁+线程池+Lock接口+线程安全集合)
42 3
|
23天前
|
缓存 算法 Java
深入理解java线程池 一
深入理解java线程池 一
39 6
|
26天前
|
监控 Java 开发者
深入理解Java并发编程:线程池的原理与实践
【5月更文挑战第85天】 在现代Java应用开发中,高效地处理并发任务是提升性能和响应能力的关键。线程池作为一种管理线程的机制,其合理使用能够显著减少资源消耗并优化系统吞吐量。本文将详细探讨线程池的核心原理,包括其内部工作机制、优势以及如何在Java中正确实现和使用线程池。通过理论分析和实例演示,我们将揭示线程池对提升Java应用性能的重要性,并给出实践中的最佳策略。
|
25天前
|
Java
如何在Java中实现线程池?
在Java中,线程池是高效管理线程的关键机制,避免了无限制创建线程的资源浪费和系统不稳定。通过`Executor`和`ExecutorService`接口,代码与具体线程池实现解耦,提供灵活性。`Executors`类简化线程池创建,适合基本需求