精华内容
下载资源
问答
  • 什么是线程池

    2021-03-05 15:43:18
    什么是线程池 创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,...

    什么是线程池

    创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。

    从JDK1.5开始,Java API提供了Executor框架可以创建不同的线程池。比如单线程池,每次处理一个任务;数目固定的线程池或者是缓存线程池(一个适合很多生存期短的任务的程序的可扩展线程池)

    new Thread的弊端

    每次new Thread新建对象性能差。

    线程缺乏统一管理,可能无限制新建线程,相互之间竞争及可能占用过多系统资源导致死机。

    四种线程池的好处

    • 重用存在的线程,减少对象创建、消亡的开销,性能佳
    • 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞
    • 提供定时执行、定期执行、单线程、并发数控制等功能。

    线程池的工作原理

    1、线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则执行第二步。

    2、线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里进行等待。如果工作队列满了,则执行第三步

    3、线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务
    在这里插入图片描述

    线程池一般流程

    • corePoolSize线程池的核心大小
    • maximumPoolSize线程池中允许的最大线程数
    • workQueue阻塞任务队列

    在这里插入图片描述

    // 创建线程池
    ExecutorService es = Executors.newCachedThreadPool(); 
    // 提交任务到线程池中
    Future f = es.submit(() -> {
        int sum = 0; 
        for (int i = 0; i <= 100; i++)
            sum += i; return sum; 
    });
    Object res = f.get(); 
    System.out.println(res);
    

    常见问题

    一般创建线程对象时不建议使用extends Thread方法? 单根继承

    一般没有返回结果时建议使用Runnable接口,如果有返回值一般建议使用Callable接口

    如果使用线程比较频繁建议使用线程池

    daemon线程

    正常情况下,非守护线程的执行时间和主线程无关,即使主线程已经结束,也不会影响子线程的运行。守护线程是为其它线程提供服务的线程

    • 守护进程的特点是当程序中主线程结束时,守护线程会自动中止

    如何将一个子线程设置为守护线程

    • 在一个线程调用start启动之前,调用方法thread.setDaemon(true);就可以将thread线程设置为守护线程.

    守护线程一般应该是一个独立的线程,它的run()方法是一个无限循环

    • 守护线程与其它线程的区别是,如果守护线程是唯一运行着的线程,程序会自动退出
    System.out.println("开始程序.......");
    Thread t=new Thread(){
        public void run(){
            while(true) 
                System.out.println("dddd.....");
        }
    };
    t.setDaemon(true);
    t.start();
    System.out.println("结束程序......");
    

    线程组

    Thread线程类中toString方法的定义

    public String toString() { 
        ThreadGroup group = getThreadGroup();//获取当前线程对象所属的线程组 
        if (group != null) {
            return "Thread[" + getName() + "," + getPriority() + "," + group.getName() + "]"; 
        } else {
            return "Thread[" + getName() + "," + getPriority() + "," + "" + "]";
        } 
    }
    

    在这里插入图片描述
    在这里插入图片描述

    所有线程都隶属于一个线程组。那可以是一个默认线程组【main】,亦可是一个创建线程时明确指定的组

    说明

    • 在创建之初,线程被限制到一个组里,而且不能改变到一个不同的组
    • 若创建多个线程而不指定一个组,它们就会与创建它的线程属于同一个组

    public Thread(ThreadGroup group, Runnable target)

    public Thread(ThreadGroup group, String name)

    public Thread(ThreadGroup group, Runnable target, String name)

    ThreadGroup myThreadGroup = new ThreadGroup("My Group");//创建线程组 
    Thread myThread = new Thread(myThreadGroup,"a thread"); //定义线程时指定对应的线程组 
    theGroup = myThread.getThreadGroup();//获取线程对象所属的线程组
    
    ThreadGroup group=new ThreadGroup("sss");
    Thread t1=new Thread(group, ()->{
        for(int i=0;i<100;i++) System.err.println(Thread.currentThread()); 
    }
           );
    t1.start();
    System.out.println(Thread.currentThread());
    //线程组的用途
    ThreadGroup tg=Thread.currentThread().getThreadGroup();
    int cc=tg.activeCount();//获取所有活跃线程线程数
    Thread[] list=new Thread[cc];
    tg.enumerate(list);//获取所有获取线程,并存放在Thread[]中 
    for(Thread temp:list)
        System.out.println(temp); 
    tg.list();//以树装结构显示当前的所有线程组
    
    展开全文
  • 1.什么是线程池? 线程池和数据库连接池非常类似,可以统一管理和维护线程,减少没有必要的开销。 2.为什么要使用线程池? 因为频繁的开启线程或者停止线程,线程需要重新从cpu从就绪状态调度到运行状态,需要...

    1.什么是线程池?

    线程池和数据库连接池非常类似,可以统一管理和维护线程,减少没有必要的开销。

     

    2.为什么要使用线程池?

    因为频繁的开启线程或者停止线程,线程需要重新从cpu从就绪状态调度到运行状态,需要发送cpu的上下文切换,效率非常低。

    线程池是复用机制,提前创建好一些固定的线程数一直在运行状态,实现复用,从而可以减少就绪到运行状态的切换。

     

    展开全文
  • 什么是线程池

    千次阅读 2019-09-07 20:07:33
    什么是线程池? 线程池就是创建若干个可执行的线程放入一个池(容器)中,有任务需要处理时,会提交到线程池中的任务队列,处理完之后线程并不会被销毁,而是仍然在线程池中等待下一个任务。 为什么要使用线程池...

    什么是线程池?

    线程池就是创建若干个可执行的线程放入一个池(容器)中,有任务需要处理时,会提交到线程池中的任务队列,处理完之后线程并不会被销毁,而是仍然在线程池中等待下一个任务。

     

    为什么要使用线程池?

    因为 Java 中创建一个线程,需要调用操作系统内核的 API,操作系统要为线程分配一系列的资源,成本很高,所以线程是一个重量级的对象,应该避免频繁创建和销毁。
    使用线程池就能很好地避免频繁创建和销毁。

     

    线程池是一种生产者——消费者模式

    先看下一个简单的 Java 线程池的代码

    
    package constxiong.concurrency.a010;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.BlockingQueue;
    
    /**
     * 简单的线程池
     * @author ConstXiong
     */
    public class ThreadPool {
    	
    	//阻塞队列实现生产者-消费者
    	BlockingQueue<Runnable> taskQueue;
    	
    	//工作线程集合
    	List<Thread> threads = new ArrayList<Thread>();
    	
    	//线程池的构造方法
    	ThreadPool(int poolSize, BlockingQueue<Runnable> taskQueue) {
    		this.taskQueue = taskQueue;
    		
    		//启动线程池对应 size 的工作线程
    		for (int i = 0; i < poolSize; i++) {
    			Thread t = new Thread(() -> {
    				while (true) {
    					Runnable task;
    					try {
    						task = taskQueue.take();//获取任务队列中的下一个任务
    						task.run();
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    			});
    			t.start();
    			threads.add(t);
    		}
    	}
    	
    	//提交执行任务
    	void execute(Runnable task) {
    		try {
    			//把任务方法放到任务队列
    			taskQueue.put(task);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    
    }

     

    线程池的使用测试

    package constxiong.concurrency.a010;
    
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingQueue;
    
    /**
     * 测试线程池的使用
     * @author ConstXiong
     */
    public class TestThreadPool {
    
    	public static void main(String[] args) {
    		// 创建有界阻塞任务队列
    		BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>(10);
    		// 创建 3个 工作线程的线程池
    		ThreadPool tp = new ThreadPool(3, taskQueue);
    		
    		//提交 10 个任务
    		for (int i = 1; i <= 10; i++) {
    			final int j = i;
    			tp.execute(() -> {
    				System.out.println("执行任务" + j);
    			});
    		}
    	}
    	
    }
    
    

    打印结果

    执行任务1
    执行任务2
    执行任务3
    执行任务6
    执行任务5
    执行任务4
    执行任务8
    执行任务7
    执行任务10
    执行任务9
    

    这个线程池的代码中

    • poolSize 是线程池工作线程的个数
    • BlockingQueue taskQueue 是用有界阻塞队列存储 Runnable 任务
    • execute(Runnable task) 提交任务
    • 线程池对象被创建,就自动启动 poolSize 个工作线程
    • 工作线程一直从任务队列 taskQueue 中取任务


    线程池的原理就是这么简单,但是 JDK 中的线程池的功能,要远比这个强大的多。

     

    JDK 中线程池的使用

    JDK 中提供的最核心的线程池工具类 ThreadPoolExecutor,在 JDK 1.8 中这个类最复杂的构造方法有 7 个参数。

    ThreadPoolExecutor(
        int corePoolSize,
        int maximumPoolSize,
        long keepAliveTime,
        TimeUnit unit,
        BlockingQueue<Runnable> workQueue,
        ThreadFactory threadFactory,
        RejectedExecutionHandler handler)
    • corePoolSize:线程池保有的最小线程数。
    • maximumPoolSize:线程池创建的最大线程数。
    • keepAliveTime:上面提到项目根据忙闲来增减人员,那在编程世界里,如何定义忙和闲呢?很简单,一个线程如果在一段时间内,都没有执行任务,说明很闲,keepAliveTime 和 unit 就是用来定义这个“一段时间”的参数。也就是说,如果一个线程空闲了keepAliveTime & unit这么久,而且线程池的线程数大于 corePoolSize ,那么这个空闲的线程就要被回收了。
    • unit:keepAliveTime 的时间单位
    • workQueue:任务队列
    • threadFactory:线程工厂对象,可以自定义如何创建线程,如给线程指定name。
    • handler:自定义任务的拒绝策略。线程池中所有线程都在忙碌,且任务队列已满,线程池就会拒绝接收再提交的任务。handler 就是拒绝策略,包括 4 种(即RejectedExecutionHandler 接口的 4个实现类)。
      • AbortPolicy:默认的拒绝策略,throws RejectedExecutionException
      • CallerRunsPolicy:提交任务的线程自己去执行该任务
      • DiscardPolicy:直接丢弃任务,不抛出任何异常
      • DiscardOldestPolicy:丢弃最老的任务,加入新的任务


    JDK 的并发工具包里还有一个静态线程池工厂类 Executors,可以方便地创建线程池,但是由于 Executors 创建的线程池内部很多地方用到了无界任务队列,在高并发场景下,无界任务队列会接收过多的任务对象,导致 JVM 抛出OutOfMemoryError,整个 JVM 服务崩溃,影响严重。所以很多公司,尤其互联网大厂已经不建议使用 Executors 去创建线程。

     

    Executors 的简介

    虽然不建议使用,作为对 JDK 的学习,还是简单介绍一下.

    1. newFixedThreadPool:创建定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程
    2. newCachedThreadPool:创建可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程,任务增加时可以自动添加新线程,线程池的容量不限制
    3. newScheduledThreadPool:创建定长线程池,可执行周期性的任务
    4. newSingleThreadExecutor:创建单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行
    5. newSingleThreadScheduledExecutor:创建单线程可执行周期性任务的线程池
    6. newWorkStealingPool:任务可窃取线程池,不保证执行顺序,当有空闲线程时会从其他任务队列窃取任务执行,适合任务耗时差异较大。


    具体使用参见 Executors 的使用示例。

     


    【Java面试题与答案】整理推荐

     

    展开全文
  • java 什么是线程池及为什么要使用线程池

    1. 为什么使用线程池

    诸如 Web 服务器、数据库服务器、文件服务器或邮件服务器之类的许多服务器应用程序都面向处理来自某些远程来源的大量短小的任务。请求以某种方式到达服务器,这种方式可能是通过网络协议(例如 HTTPFTP 或 POP)、通过 JMS 队列或者可能通过轮询数据库。不管请求如何到达,服务器应用程序中经常出现的情况是:单个任务处理的时间很短而请求的数目却是巨大的。

    构建服务器应用程序的一个简单模型是:每当一个请求到达就创建一个新线程,然后在新线程中为请求服务。实际上对于原型开发这种方法工作得很好,但如果试图部署以这种方式运行的服务器应用程序,那么这种方法的严重不足就很明显。每个请求对应一个线程(thread-per-request)方法的不足之一是:为每个请求创建一个新线程的开销很大;为每个请求创建新线程的服务器在创建和销毁线程上花费的时间和消耗的系统资源要比花在处理实际的用户请求的时间和资源更多。

    除了创建和销毁线程的开销之外,活动的线程也消耗系统资源。在一个 JVM 里创建太多的线程可能会导致系统由于过度消耗内存而用完内存或切换过度。为了防止资源不足,服务器应用程序需要一些办法来限制任何给定时刻处理的请求数目。

    线程池为线程生命周期开销问题和资源不足问题提供了解决方案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。其好处是,因为在请求到达时线程已经存在,所以无意中也消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使应用程序响应更快。而且,通过适当地调整线程池中的线程数目,也就是当请求的数目超过某个阈值时,就强制其它任何新到的请求一直等待,直到获得一个线程来处理为止,从而可以防止资源不足。

    2. 使用线程池的风险

    虽然线程池是构建多线程应用程序的强大机制,但使用它并不是没有风险的。用线程池构建的应用程序容易遭受任何其它多线程应用程序容易遭受的所有并发风险,诸如同步错误和死锁,它还容易遭受特定于线程池的少数其它风险,诸如与池有关的死锁、资源不足和线程泄漏。

    2.1 死锁

    任何多线程应用程序都有死锁风险。当一组进程或线程中的每一个都在等待一个只有该组中另一个进程才能引起的事件时,我们就说这组进程或线程 死锁了。死锁的最简单情形是:线程 持有对象 的独占锁,并且在等待对象 的锁,而线程 持有对象 的独占锁,却在等待对象 的锁。除非有某种方法来打破对锁的等待(Java 锁定不支持这种方法),否则死锁的线程将永远等下去。

    虽然任何多线程程序中都有死锁的风险,但线程池却引入了另一种死锁可能,在那种情况下,所有池线程都在执行已阻塞的等待队列中另一任务的执行结果的任务,但这一任务却因为没有未被占用的线程而不能运行。当线程池被用来实现涉及许多交互对象的模拟,被模拟的对象可以相互发送查询,这些查询接下来作为排队的任务执行,查询对象又同步等待着响应时,会发生这种情况。

    2.2 资源不足

    线程池的一个优点在于:相对于其它替代调度机制(有些我们已经讨论过)而言,它们通常执行得很好。但只有恰当地调整了线程池大小时才是这样的。线程消耗包括内存和其它系统资源在内的大量资源。除了 Thread 对象所需的内存之外,每个线程都需要两个可能很大的执行调用堆栈。除此以外,JVM 可能会为每个 Java 线程创建一个本机线程,这些本机线程将消耗额外的系统资源。最后,虽然线程之间切换的调度开销很小,但如果有很多线程,环境切换也可能严重地影响程序的性能。

    如果线程池太大,那么被那些线程消耗的资源可能严重地影响系统性能。在线程之间进行切换将会浪费时间,而且使用超出比您实际需要的线程可能会引起资源匮乏问题,因为池线程正在消耗一些资源,而这些资源可能会被其它任务更有效地利用。除了线程自身所使用的资源以外,服务请求时所做的工作可能需要其它资源,例如 JDBC 连接、套接字或文件。这些也都是有限资源,有太多的并发请求也可能引起失效,例如不能分配 JDBC 连接。

    2.3 并发错误

    线程池和其它排队机制依靠使用 wait()  notify() 方法,这两个方法都难于使用。如果编码不正确,那么可能丢失通知,导致线程保持空闲状态,尽管队列中有工作要处理。使用这些方法时,必须格外小心。而最好使用现有的、已经知道能工作的实现,例如 util.concurrent 包。

    2.4 线程泄漏

    各种类型的线程池中一个严重的风险是线程泄漏,当从池中除去一个线程以执行一项任务,而在任务完成后该线程却没有返回池时,会发生这种情况。发生线程泄漏的一种情形出现在任务抛出一个 RuntimeException 或一个 Error 时。如果池类没有捕捉到它们,那么线程只会退出而线程池的大小将会永久减少一个。当这种情况发生的次数足够多时,线程池最终就为空,而且系统将停止,因为没有可用的线程来处理任务。

    有些任务可能会永远等待某些资源或来自用户的输入,而这些资源又不能保证变得可用,用户可能也已经回家了,诸如此类的任务会永久停止,而这些停止的任务也会引起和线程泄漏同样的问题。如果某个线程被这样一个任务永久地消耗着,那么它实际上就被从池除去了。对于这样的任务,应该要么只给予它们自己的线程,要么只让它们等待有限的时间。

    2.5 请求过载

    仅仅是请求就压垮了服务器,这种情况是可能的。在这种情形下,我们可能不想将每个到来的请求都排队到我们的工作队列,因为排在队列中等待执行的任务可能会消耗太多的系统资源并引起资源缺乏。在这种情形下决定如何做取决于您自己;在某些情况下,您可以简单地抛弃请求,依靠更高级别的协议稍后重试请求,您也可以用一个指出服务器暂时很忙的响应来拒绝请求。

    3. 有效使用线程池的准则

    只要您遵循几条简单的准则,线程池可以成为构建服务器应用程序的极其有效的方法:

    不要对那些同步等待其它任务结果的任务排队。这可能会导致上面所描述的那种形式的死锁,在那种死锁中,所有线程都被一些任务所占用,这些任务依次等待排队任务的结果,而这些任务又无法执行,因为所有的线程都很忙。

    在为时间可能很长的操作使用合用的线程时要小心。如果程序必须等待诸如 I/O 完成这样的某个资源,那么请指定最长的等待时间,以及随后是失效还是将任务重新排队以便稍后执行。这样做保证了:通过将某个线程释放给某个可能成功完成的任务,从而将最终取得某些进展。

    理解任务。要有效地调整线程池大小,您需要理解正在排队的任务以及它们正在做什么。它们是 CPU 限制的(CPU-bound)吗?它们是I/O 限制的(I/O-bound)吗?您的答案将影响您如何调整应用程序。如果您有不同的任务类,这些类有着截然不同的特征,那么为不同任务类设置多个工作队列可能会有意义,这样可以相应地调整每个池。

    4. 线程池的大小设置

    调整线程池的大小基本上就是避免两类错误:线程太少或线程太多。幸运的是,对于大多数应用程序来说,太多和太少之间的余地相当宽。

    请回忆:在应用程序中使用线程有两个主要优点,尽管在等待诸如 I/O 的慢操作,但允许继续进行处理,并且可以利用多处理器。在运行于具有 个处理器机器上的计算限制的应用程序中,在线程数目接近 时添加额外的线程可能会改善总处理能力,而在线程数目超过 N时添加额外的线程将不起作用。事实上,太多的线程甚至会降低性能,因为它会导致额外的环境切换开销。

    线程池的最佳大小取决于可用处理器的数目以及工作队列中的任务的性质。若在一个具有 N 个处理器的系统上只有一个工作队列,其中全部是计算性质的任务,在线程池具有 或 N+1 个线程时一般会获得最大的 CPU 利用率。

    对于那些可能需要等待 I/O 完成的任务(例如,从套接字读取 HTTP 请求的任务),需要让池的大小超过可用处理器的数目,因为并不是所有线程都一直在工作。通过使用概要分析,您可以估计某个典型请求的等待时间(WT)与服务时间(ST)之间的比例。如果我们将这一比例称之为 WT/ST,那么对于一个具有 个处理器的系统,需要设置大约 N*(1+WT/ST) 个线程来保持处理器得到充分利用。

    处理器利用率不是调整线程池大小过程中的唯一考虑事项。随着线程池的增长,您可能会碰到调度程序、可用内存方面的限制,或者其它系统资源方面的限制,例如套接字、打开的文件句柄或数据库连接等的数目。

    5. 常用的几种线程池

    5.1 newCachedThreadPool

    创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

    这种类型的线程池特点是:

    • 工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
    • 如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
    • 在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。

    示例代码如下:

    复制代码
     1 package test;
     2 import java.util.concurrent.ExecutorService;
     3 import java.util.concurrent.Executors;
     4 public class ThreadPoolExecutorTest {
     5  public static void main(String[] args) {
     6   ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
     7   for (int i = 0; i < 10; i++) {
     8    final int index = i;
     9    try {
    10     Thread.sleep(index * 1000);
    11    } catch (InterruptedException e) {
    12     e.printStackTrace();
    13    }
    14    cachedThreadPool.execute(new Runnable() {
    15     public void run() {
    16      System.out.println(index);
    17     }
    18    });
    19   }
    20  }
    21 }
    复制代码

    5.2 newFixedThreadPool

    创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。

    FixedThreadPool是一个典型且优秀的线程池,它具有线程池提高程序效率和节省创建线程时所耗的开销的优点。但是,在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。

    示例代码如下:

     

    复制代码
    package test;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    public class ThreadPoolExecutorTest {
     public static void main(String[] args) {
      ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
      for (int i = 0; i < 10; i++) {
       final int index = i;
       fixedThreadPool.execute(new Runnable() {
        public void run() {
         try {
          System.out.println(index);
          Thread.sleep(2000);
         } catch (InterruptedException e) {
          e.printStackTrace();
         }
        }
       });
      }
     }
    }
    复制代码

     

    因为线程池大小为3,每个任务输出indexsleep 2秒,所以每两秒打印3个数字。
    定长线程池的大小最好根据系统资源进行设置如Runtime.getRuntime().availableProcessors()。

     

    5.3 newSingleThreadExecutor

    创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的

    示例代码如下:

     

    复制代码
    package test;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    public class ThreadPoolExecutorTest {
     public static void main(String[] args) {
      ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
      for (int i = 0; i < 10; i++) {
       final int index = i;
       singleThreadExecutor.execute(new Runnable() {
        public void run() {
         try {
          System.out.println(index);
          Thread.sleep(2000);
         } catch (InterruptedException e) {
          e.printStackTrace();
         }
        }
       });
      }
     }
    } 
    复制代码

     

    5.4 newScheduleThreadPool

    创建一个定长的线程池,而且支持定时的以及周期性的任务执行支持定时及周期性任务执行。

    延迟3秒执行延迟执行示例代码如下:

     

    复制代码
    package test;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    public class ThreadPoolExecutorTest {
     public static void main(String[] args) {
      ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
      scheduledThreadPool.schedule(new Runnable() {
       public void run() {
        System.out.println("delay 3 seconds");
       }
      }, 3, TimeUnit.SECONDS);
     }
    }
    复制代码

     

    表示延迟1秒后每3秒执行一次定期执行示例代码如下:

     

    复制代码
    package test;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    public class ThreadPoolExecutorTest {
     public static void main(String[] args) {
      ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
      scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
       public void run() {
        System.out.println("delay 1 seconds, and excute every 3 seconds");
       }
      }, 1, 3, TimeUnit.SECONDS);
     }
    }
    复制代码

     

    展开全文
  • 什么是线程池? 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。...
  • 什么是线程池?

    千次阅读 2018-04-03 21:33:37
    什么是线程池线程池的概念大家应该都很清楚,帮我们重复管理线程,避免创建大量的线程增加开销。除了降低开销以外,线程池也可以提高响应速度,了解点 JVM 的同学可能知道,一个对象的创建大概需要经过以下几步:...
  • 什么是线程池,有哪些常用线程池? 就是事先创建若干个可执行的线程放入一个池(容器) 中, 需要的时候从池中获取线程不用自行创建, 使用完毕不需 要销毁线程而是放回池中, 从而减少创建和销毁线程对象的开销 ...
  • 1、什么是线程池: 线程池的概念大家应该都很清楚,帮我们重复管理线程,避免创建大量的线程增加开销。 线程池就是提前创建若干个线程,如果有任务需要处理,线程池里的线程就会处理任务,处理完之后线程并不会被...
  • 1、什么是线程池: java.util.concurrent.Executors提供了一个 java.util.concurrent.Executor接口的实现用于创建线程池 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,...
  • 什么是线程池,如何使用?       线程池就是将多个线程对象放到一个容器中,当使用的时候就不用new线程而是直接区池中拿线程即可,节省了开辟子线程的时间,提高了代码执行效率。 ...
  • 什么是线程池? Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序 都可以使用线程池。 主要处理流程: 第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的...
  • 1. 为什么需要线程池?  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。   假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 ...
  • 这篇文章的目的是为了解释线程模型——什么是线程池、以及怎样正确地配置线程池。 单线程模型 让我们从一些基础的线程模型开始,然后再随着线程模型的演变进行更深一步的学习。你使用的任何应用服务器或框架,如...
  • 1、什么是线程池? 答:其实说白了,线程池是一种多线程处理方法,帮我们管理线程,避免创建大量的线程增加服务器压力。 其实在面向对象编程中,对象创建和销毁是很费时间的;那么大家就会说,使用线程技术不就好了...
  • 线程题—什么是线程池? 概念性的知识,上来就是整,读个三五遍熟悉一下,然后就背下来,简单、粗暴、有效。 在面向对象编程中,创建和销毁对象是非常浪费时间的,因为创建一个对象要获取内存资源或者其他更多的资源...
  • 线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用new线程而是直接去池中拿线程即可,节省了开辟子线程的时间,提高的代码执行效率。在JDK的java.util.concurrent.Executors中提供了生成多种线程池的...
  • 什么是线程池? 线程池是管理线程对象的容器,将任务提交到线程池后,线程池会使用线程池中的线程来执行任务,线程使用完毕后不需要销毁而是放回池中,从而可以减少创建和销毁线程对象的开销。 如何设计一个动态...
  • 1.什么是线程池 2.为什么要使用线程池 2.1 降低资源消耗 2.2 提高系统的响应速度 2.3 防止过多的线程搞坏系统 3.线程池主要参数 3.1 corePoolSize 3.2 maximumPoolSize 3.3 keepAliveTime 3.4 unit 3.5 ...
  • 2021版Java线程池教程 全集 2021版Java线程池教程 2021版Java多线程教程 代码 Task.class package main; public class Task implements Runnable { @Override public void run() { System.out.println(Thread...
  • 一个线程池管理了一组工作线程,同时它还包括了一个用于放置等待执行任务的任务队列(阻塞队列) 默认情况下,在创建了线程池后,线程池中的线程数为0.当任务提交给线程池之后的处理策略如下: 1:如果此时线程池中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,438
精华内容 3,375
关键字:

什么是线程池