线程池与线程 java

1.为什么要使用线程池

在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,服务器在创建和销毁线程上花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。为了防止资源不足,服务器应用程序需要采取一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利
用已有对象来进行服务,这就是“池化资源”技术产生的原因。

线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使用应用程序响应更快。另外,通过适当的调整线程中的线程数目可以防止出现资源不足的情况。

2.线程池的组成部分

一个比较简单的线程池至少应包含线程池管理器、工作线程、任务列队、任务接口等部分。其中线程池管理器的作用是创建、销毁并管理线程池,将工作线程放入线程池中;工作线程是一个可以循环执行任务的线程,在没有任务是进行等待;任务列队的作用是提供一种缓冲机制,将没有处理的任务放在任务列队中;任务接口是每个任务必须实现的接口,主要用来规定任务的入口、任务执行完后的收尾工作、任务的执行状态等,工作线程通过该接口调度任务的执行。

线程池管理器至少有下列功能:创建线程池,销毁线程池,添加新任务。

工作线程是一个可以循环执行任务的线程,在没有任务时将等待。

任务接口是为所有任务提供统一的接口,以便工作线程处理。任务接口主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等。

3.线程池适合应用的场合

当一个服务器接受到大量短小线程的请求时,使用线程池技术是非常合适的,它可以大大减少线程的创建和销毁次数,提高服务器的工作效率。但是线程要求的运动时间比较长,即线程的运行时间比…….

以上信息来自如下文章:http://www.blogjava.net/stevenjohn/archive/2011/12/12/366161.html


没有案例,始终让人懂不起。下面来看看案例

package com.broadtech.bdvmonitor.test;

public class M1 implements Runnable {

	public void run() {
		// TODO Auto-generated method stub
		try {
			Thread.sleep(2000); //睡2秒
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("第1次");
	}

}
package com.broadtech.bdvmonitor.test;

public class M2 implements Runnable {

	public void run() {
		// TODO Auto-generated method stub
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("第2次");
	}

}

package com.broadtech.bdvmonitor.test;

public class M3 implements Runnable {

	public void run() {
		// TODO Auto-generated method stub
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("第3次");
	}

}

package com.broadtech.bdvmonitor.test;

public class M4 implements Runnable {

	public void run() {
		// TODO Auto-generated method stub
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("第4次");
	}

}

上述4个类:

串行运行, 需要2秒+2秒+2秒+2秒=  8秒。

并行运行,就2秒完成4个类的run方法。



测试类

package com.broadtech.bdvmonitor.test;

import java.io.File;
import java.util.Queue;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
 
 

public class SystemOutTest {
 
	public static void main(String[] args) throws Exception  {
		// TODO Auto-generated method stub

        // 创建一个可重用固定线程数的线程池  
        ExecutorService pool = Executors.newFixedThreadPool(5);  
        
		long start    = System.currentTimeMillis();
		SystemOutTest so =new SystemOutTest();
		 
		M1 m1 =new M1();
		M2 m2 =new M2();
		M3 m3 =new M3();
		M4 m4 =new M4();
		 
	    Thread t1 = new Thread(m1);   
        Thread t2 = new Thread(m2);  
        Thread t3 = new Thread(m3);  
        Thread t4 = new Thread(m4);   
        
        // 将线程放入池中进行执行  
        pool.execute(t1);  
        pool.execute(t2);  
        pool.execute(t3);  
        pool.execute(t4);   
        
    	long duration = System.currentTimeMillis() - start;
		System.out.println(String.format("parallel  time cost is %d ms",  duration));
		
        // 关闭线程池  
        pool.shutdown();

	}
  
	 
	
}


注意:5ms 是主类执行的时间,剩下的2秒,是M1 M2 M3 M4 并行执行的时间。

如果需要测试,可以把测试代码在自己机器修改。



猜你喜欢

转载自blog.csdn.net/shushugood/article/details/80894668