多线程使用
在java中,多线程得主要实现方式有四种:继承Thread类,实现Runnable接口、实现callable接口通过FutureTask包装器来创建Thread线程,使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,而后两种是带返回值的。除此之外,通过Timer启动定时任务,或者通过像Spring Task和quartz这样的第三方任务调度框架也可以开启多线程任务
继承Thread类创建线程
Thread类本质上也是实现了Runnable接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程比较简单,通过继承Thread类并复写run()方法,就可以启动新线程并执行自己定义的run()方法
public class ThreadDemo extends Thread {
public ThreadDemo(String name) {
// 设置当前线程的名字
this.setName(name);
}
@Override
public void run() {
System.out.println("当前运行的线程名为: " + Thread.currentThread().getName());
}
public static void main(String[] args) throws Exception {
// 注意这里,要调用start方法才能启动线程,不能调用run方法
new ThreadDemo("MyThreadOne").start();
new ThreadDemo("MyThreadTwo").start();
}
}
输出结果:
当前运行的线程名为: MyThreadOne
当前运行的线程名为: MyThreadTwo
实现Runnable接口创建线程
由于Java是单继承机制,如果自己的类已经继承自另一个类,则无法再直接继承Thread类,此时,可以通过实现Runnable接口来实现多线程。
实现Runnable接口并实现其中的run方法,然后通过构造Thread实例,传入Runnable实现类,然后调用Thread的start方法即可开启一个新线程。
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("当前运行的线程名为: " + Thread.currentThread().getName());
}
public static void main(String[] args) throws Exception {
MyRunnable runnable = new MyRunnable();
new Thread(runnable, "MyThreadOne").start();
new Thread(runnable, "MyThreadTwo").start();
}
}
输出结果:
当前运行的线程名为: MyThreadOne
当前运行的线程名为: MyThreadTwo
线程池使用
线程池本质是池化技术
的应用,和连接池类似,创建连接与关闭连接属于耗时操作,创建线程与销毁线程也属于重操作,为了提高效率,先提前创建好一批线程,当有需要使用线程时从线程池取出,用完后放回线程池,这样避免了频繁创建与销毁线程。
核心参数
线程池的核心参数决定了池的类型,进而决定了池的特性。
参数 | 解释 | 行为 |
---|---|---|
corePoolSize | 核心线程数 | 池中长期维护的线程数量,不主动回收 |
maximumPoolSize | 最大线程数 | 最大线程数大于等于核心线程数 |
keepAliveTime | 线程最大空闲时间 | 非核心线程最大空闲时间,超时回收线程 |
workQueue | 工作队列 | 工作队列直接决定线程池的类型 |
Executors类默认创建线程池与参数对应关系。
线程池 | corePoolSize | maximumPoolSize | keepAliveTime | workQueue |
---|---|---|---|---|
newCachedThreadPool | 0 | Integer.MAX_VALUE | 60 | SynchronousQueue |
newSingleThreadExecutor | 1 | 1 | 0 | LinkedBlockingQueue |
newFixedThreadPool | N | N | 0 | LinkedBlockingQueue |
newScheduledThreadPool | N | Integer.MAX_VALUE | 0 | DelayedWorkQueue |
线程池对比
线程池 | 特点 | 适用场景 |
---|---|---|
newCachedThreadPool | 超时未使用的线程回自动销毁,有新任务时自动创建 | 适用于低频、轻量级的任务。回收线程的目的是节约线程长时间空闲而占有的资源。 |
newSingleThreadExecutor | 线程池中有且只有一个线程 | 顺序执行任务 |
newFixedThreadPool | 线程池中有固定数量的线程,且一直存在 | 适用于高频的任务,即线程在大多数时间里都处于工作状态。 |
newScheduledThreadPool | 定时线程池 | 与定时调度相关联 |