目录
一、概述
线程(thread):一个程序内部的一条执行路径
单线程:程序中只有一条执行路径
多线程(multithreading):实现多条执行流程的技术
多线程优点:更好地利用cpu的资源;改善程序的结构;将复杂的进程分为多个线程独立运行,利于理解和维护;提高应用程序的响应能力
定时任务:任务体可以定时执行(延迟执行,定时执行,定期循环执行)
二、Java多线程实现常用方法
1. 继承Thread
步骤:继承thread--》重写run方法--》创建线程对象--》调用start方法启动
说明:编程简单,存在单继承的局限性
示例:
public class ThreadTest {
public static void main(String[] args) {
// 实现方式1---继承Thread
TaskForExt taskForExt1 = new TaskForExt();
TaskForExt taskForExt2 = new TaskForExt();
taskForExt1.start();
taskForExt2.start();
}
}
/**
* 继承thread
*/
class TaskForExt extends Thread{
/**
* 重写run方法
*/
@Override
public void run(){
for(int i=0; i<3; i++){
System.out.println(Thread.currentThread().getName()+"===>"+i);
}
}
}
输出:(多线程同步执行,打印顺序不固定)
Thread-0===>0
Thread-1===>0
Thread-1===>1
Thread-0===>1
Thread-1===>2
Thread-0===>2
2. 重写Runnable接口
步骤:实现runnable--》重写run方法--》创建线程对象--》调用start方法启动
(还可以使用匿名内部类简化代码)
说明:创建过程稍微复杂一点点,扩展性好
示例:
public class ThreadTest {
public static void main(String[] args) {
// 实现方式2---实现Runnable
Runnable taskForImpl = new TaskForImpl();
Thread t1 = new Thread(taskForImpl);
Thread t2 = new Thread(taskForImpl);
t1.start();
t2.start();
}
}
/**
* 实现Runnable
*/
class TaskForImpl implements Runnable{
/**
* 重写run方法
*/
@Override
public void run(){
for(int i=0; i<3; i++){
System.out.println(Thread.currentThread().getName()+"===>"+i);
}
}
}
输出:(多线程同步执行,打印顺序不固定)
Thread-0===>0
Thread-1===>0
Thread-0===>1
Thread-1===>1
Thread-0===>2
Thread-1===>2
3. 线程池
线程池:可以复用线程的技术
方式1:通过ExecutorService的实现类ThreadPoolExecutor创建线程池对象
方式2:使用Executors工具类的不同方法创建不同类型线程池对象
在线程池里执行Runnable任务
示例:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadTest {
public static void main(String[] args) {
// 实现方式3---线程池
// 参数:int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue
ExecutorService pool = new ThreadPoolExecutor(2, 5, 6, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5));
Runnable target = new TaskForImpl();
pool.execute(target);
pool.execute(target);
}
}
/**
* 实现Runnable
*/
class TaskForImpl implements Runnable{
/**
* 重写run方法
*/
@Override
public void run(){
for(int i=0; i<3; i++){
System.out.println(Thread.currentThread().getName()+"===>"+i);
}
}
}
输出:(多线程同步执行,打印顺序不固定)
pool-1-thread-2===>0
pool-1-thread-1===>0
pool-1-thread-2===>1
pool-1-thread-1===>1
pool-1-thread-1===>2
pool-1-thread-2===>2
三、利用线程池实现定时任务
- 使用Executors工具类的newScheduledThreadPool方法创建线程池对象
- 调用线程池的scheduleAtFixedRate方法创建定时任务
示例:
任务1(线程A),延迟1秒执行,每5秒循环一次
任务2(线程B),延迟3秒执行,每5秒循环一次
import java.util.Date;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class PoolTask {
public static void main(String[] args) {
// 创建核心线程数量为2的线程池
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
// 任务1,延迟1秒执行,每5秒循环一次
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程A "+new Date());
}
},1,5, TimeUnit.SECONDS);
// 任务2,延迟3秒执行,每5秒循环一次
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程B "+new Date());
}
},3,5, TimeUnit.SECONDS);
// 关闭线程池
// pool.shutdown();
}
}
输出:
pool-1-thread-1线程A Wed Jul 20 10:17:59 CST 2022
pool-1-thread-2线程B Wed Jul 20 10:18:01 CST 2022
pool-1-thread-1线程A Wed Jul 20 10:18:04 CST 2022
pool-1-thread-2线程B Wed Jul 20 10:18:06 CST 2022
pool-1-thread-1线程A Wed Jul 20 10:18:09 CST 2022
pool-1-thread-2线程B Wed Jul 20 10:18:11 CST 2022