介绍Java的线程、线程池等操作
public class ThreadTest extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
new ThreadTest().start();
}
}
import java.util.Date;
@Slf4j
public class ThreadTest extends Thread{
@Override
public void run() {
log.info("线程名称:{} , 当前时间:{}" , Thread.currentThread().getName() , new Date().getTime() );
}
public static void main(String[] args) {
while (true) {
try {
new ThreadTest().start();
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.info("主线程常驻");
}
}
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ThreadTest extends Thread{
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
log.info("Hello {}" , "world");
}
};
thread.start();
}
}
继承了Thread类之后,就不能继承其他类
成员内部类(外部类内部使用,外部类外部使用)
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Outer {
public static void main(String[] args) {
Inner inner = new Outer().initTest();
log.info(inner.innerTest());
}
public Inner initTest(){
Inner inner = new Inner();
return inner;
}
class Inner{
public Inner(){
}
public Inner(String s){
}
public String innerTest(){
return "Inner Hello world";
}
}
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Outer {
public static void main(String[] args) {
Inner inner = new Inner();
log.info(inner.innerTest());
}
public void initTest(){
Inner inner = new Inner();
}
static class Inner{
public Inner(){
}
public Inner(String s){
}
public String innerTest(){
return "Inner Hello world";
}
}
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Outer {
public static void main(String[] args) {
Outer outer = new Outer();
outer.sayHello();
}
public void sayHello(){
IMessage iMessage = new IMessage() {
//匿名类
@Override
public String sayHello() {
return "Hello world";
}
};
log.info(iMessage.sayHello());
}
interface IMessage{
String sayHello();
}
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class StatSales implements Runnable{
@Override
public void run() {
log.info("统计销量");
}
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
log.info("Hello world");
}
};
thread.start();
}
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("统计成绩");
}
};
new Thread(runnable).start();
}
// 使用 Lambda 匿名 Runnable 方式
Thread t3 = new Thread(() -> {
//添加业务方法…
});
// 启动线程
t3.start();
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("统计平均寿命");
});
thread.start();
}
不能获得程序的执行结果
把函数作为一个方法的参数
表达式语法:
(parameters) -> expression
或
(parameters) ->{ statements; }
说明:
举例:
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
FutureTask+Callable
public class StatScore implements Callable<Double> {
@Override
public Double call() throws Exception {
//统计分数的逻辑
return 88.98;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
StatScore statScore = new StatScore();
//跟FutureTask 关联上
FutureTask<Double> doubleFutureTask = new FutureTask<>(statScore);
//跟Thread关联上
Thread thread = new Thread(doubleFutureTask);
thread.start();
log.info(String.valueOf(doubleFutureTask.get()));
}
public class StatScore {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Order order = new Order();
order.setOrderId(100);
order.setPayStatus(1);
order.setOrderTime( "2023-05-31");
order.setOrderId(1001);
order.setUserId(10001);
FutureTask<List<Order>> doubleFutureTask = new FutureTask<>( ()-> {
// 获取订单列表
List<Order> orderList = new ArrayList<>();
orderList.add(order);
Thread.sleep(3000);
System.out.println("return list");
return orderList;
});
//跟Thread关联上
Thread thread = new Thread(doubleFutureTask);
thread.start();
try {
System.out.println( doubleFutureTask.get(500 , TimeUnit.MILLISECONDS) );
} catch (TimeoutException e) {
System.out.println("获取订单列表接口超时");
}
System.out.println("------------------------end------------------------------");
}
}
线程池就是存放线程的池子,池子里存放了很多可以复用的线程。
使用线程池的优势
//创建一个单线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
ExecutorService executorService = Executors.newSingleThreadExecutor();
//创建一个定长的线程池,可控制最大并发数,超出的线程进行队列等待。 ExecutorService executorService =
Executors.newFixedThreadPool(2); //可以创建定长的、支持定时任务,周期任务执行。
ExecutorService executorService = Executors.newScheduledThreadPool(2);
//创建一个可以缓存的线程池,如果线程池长度超过处理需要,可以灵活回收空闲线程,没回收的话就新建线程 ExecutorService
executorService = Executors.newCachedThreadPool(); //创建一个具有抢占式操作的线程池
ExecutorService executorService = Executors.newWorkStealingPool();
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
参数说明:
参数 | 含义 | 解释 |
---|---|---|
corePoolSize | 该线程池中核心线程数最大值 | 核心线程生命周期无限,即使空闲也不会死亡 |
maximumPoolSize | 线程总数最大值 | 任务队列满了以后当有新任务进来则会增加一个线程来处理新任务(线程总数<maximumPoolSize ) |
keepAliveTime | 闲置超时时间 | 当线程数大于核心线程数时,超过keepAliveTime时间将会回收非核心线程 |
unit | keepAliveTime 的单位 | |
workQueue | 线程池中的任务队列 | * |
threadFactory | 为线程池提供创建新线程的线程工厂 | * |
RejectedExecutionHandler | 饱和策略 | 抛出异常专用,当队列和最大线程池都满了之后的饱和策略。 |
ThreadPoolExecutor的饱和策略可以通过调用setRejectedExecutionHandler来修改。JDK提供了几种不同的RejectedExecutionHandler实现,每种实现都包含有不同的饱和策略:AbortPolicy、CallerRunsPolicy、DiscardPolicy和DiscardOldestPolicy。
拒绝策略如下:
RejectedExecutionHandler rejected = null;
//默认策略,阻塞队列满,则丢任务、抛出异常
rejected = new ThreadPoolExecutor.AbortPolicy();
//阻塞队列满,则丢任务,不抛异常
rejected = new ThreadPoolExecutor.DiscardPolicy();
//删除队列中最旧的任务(最早进入队列的任务),尝试重新提交新的任务
rejected = new ThreadPoolExecutor.DiscardOldestPolicy();
//队列满,不丢任务,不抛异常,若添加到线程池失败,那么主线程会自己去执行该任务
rejected = new ThreadPoolExecutor.CallerRunsPolicy();
总结: 就是被拒绝的任务,直接在主线程中运行,不再进入线程池。