在Java中,多线程有着广泛运用。在实际应用中,好的软件设计不建议手动创建和销毁线程。线程的创建和销毁是非常耗 CPU 和内存资源的,因为这需要 JVM 和操作系统的参与。为此,我们在面临多线程问题时,通常会采用线程池。一般情况下,每个线程池会由这些模块组成:一个任务队列,一个工作线程的集合,一个线程工厂,管理线程状态的元数据。
线程池可以解决两个问题:一是由于减少了每个任务调用的开销,它们通常可以在执行大量异步任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行任务集时使用的线程)的方法;二是每个 ThreadPoolExecutor 还维护着一些基本的统计数据,如完成的任务数。
线程池均位于 java.util.concurrent包中。
ThreadPoolExecutor类的继承关系为:
public class ThreadPoolExecutor extends AbstractExecutorService
其中,抽象类 AbstractExecutorService的继承关系为:
public abstract class AbstractExecutorService extends Object implements ExecutorService
ExecutorService接口的继承关系为:
public interface ExecutorService extends Executor
Executor是一个顶级接口。
在实际应用中,我们可以采用Executors的工厂方法Executors.newCachedThreadPool()(无界限程池,可以进行自动线程回收),Executors.newFixedThreadPool(int)(固定大小线程池),或Executors.newSingleThreadExecutor()(单个后台线程)来生成线程池,这些方法生成的线程池均为大多数使用场景预定义了设置。
Executors的的继承关系为:
public class Executors extends Object
由于创建子线程可以有继承Thread类,实现Runnable接口,以及实现Callable接口三种方式,所以,我这里先通过这三种方式创建线程,然后再通过一个测试类通过线程池来运行。
MyThread.java中的代码如下:
public class MyThread extends Thread{public MyThread(String name){super(name);}int num=10;@Overridepublic void run() {while(num>=0){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(getName()+"正在数:"+num);num--;}}}MyRun.java中的代码如下:
public class MyRun implements Runnable {public MyRun(String name){Thread.currentThread().setName(name);}int num=10;@Overridepublic void run() {while(num>=0){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"正在数:"+num);num--;}}}
MyCall.java中的代码如下:
public class MyCall implements Callable<String> {int num=10;@Overridepublic String call() throws Exception {while(num>=0){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"正在数:"+num);num--;}return Thread.currentThread().getName()+"顺利执行";}}
测试文件Test.java中的代码如下:
import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.ThreadPoolExecutor;public class Test {//采用newFixedThreadPool()方法创建线程池,设置线程池中有2个线程static ThreadPoolExecutor pool=(ThreadPoolExecutor) Executors.newFixedThreadPool(2);//或者采用下述方式生成线程连接池// static ExecutorService pool=Executors.newFixedThreadPool(2);public static void main(String[] args) {Future<String> s1 = pool.submit(new MyCall());Future<String> s2 = pool.submit(new MyCall());try {System.out.println(s1.get());System.out.println(s2.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}//切记:线程池不是线程执行结束就终止,而是手动终止pool.shutdown();}public static void main2(String[] args) {pool.submit(new MyRun("张三"));pool.submit(new MyRun("李四"));pool.submit(new MyRun("王五"));pool.submit(new MyRun("赵六"));//切记:线程池不是线程执行结束就终止,而是手动终止pool.shutdown();}public static void main1(String[] args) {pool.submit(new MyThread("张三"));pool.submit(new MyThread("李四"));pool.submit(new MyThread("王五"));pool.submit(new MyThread("赵六"));//切记:线程池不是线程执行结束就终止,而是手动终止pool.shutdown();}}