一、创建线程的方式
1.继承Thread类。自定义一个类,继承Thread类,并重写run方法,该run方法包含线程要执行的任务。在main函数中创建这个自定义线程类的对象,然后调用start方法启动线程。
static class MyThread extends Thread{
@Override
public void run(){
//业务需求
}
}
2.实现Runnable接口。自定义一个类,实现Runnable接口,并覆盖其中的run方法,该run方法同样包含线程要执行的任务。在main函数中创建这个自定义线程类的对象,然后将其传递给Thread类的构造函数,创建Thread对象,最后调用start方法启动线程。
class MyThread implements Runnable {
@Override
public void run() {
//业务需求
}
}
3.实现Callable接口。自定义一个类,实现Callable接口,并覆盖其中的call方法,该call方法包含线程要执行的任务,并且有返回值。在main函数中创建这个自定义线程类的对象,然后将其传递给FutureTask类的构造函数,创建FutureTask对象,最后使用FutureTask对象作为Thread对象的target来创建并启动新线程,并通过Future对象的get方法来获得子线程执行结束后的返回值
class MyThread implements Callable<String> {
@Override
public String call() throws Exception {
//业务需求
}
}
二、线程常用方法
1.start():启动线程并开始执行线程的任务。
2.run():线程的主体方法,包含线程要执行的代码逻辑。
3.sleep():使线程暂停指定的时间,单位是毫秒。
4.join():等待该线程执行完毕,然后再执行其他线程。
5.interrupt():中断线程的执行。
6.isAlive():判断线程是否处于活动状态。
7.yield():暂停当前正在执行的线程对象,让其他线程执行。
8.setPriority():设置线程的优先级。
9.getName():获取线程的名称。
10.currentThread():获取当前正在执行的线程对象。
三、子线程结束执行主线程
1.针对我们创建的线程集合执行结束执行主线程调用线程内方法join
//线程集合
List<Thread> threadList = new ArrayList<>();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
//业务逻辑
} catch (Exception e) {
e.printStackTrace();
}
}
});
threadList.add(thread);
// 遍历出每一个集合
for (Thread thread : threadList) {
thread.start();
}
for (Thread thread : threadList) {
try {
thread.join();
} catch (Exception e) {
log.info("等待结束错误");
}
}
2.线程池采用线程sleep方法,让主线程睡眠放开cpu抢占权
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 0, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
for (Long key : collect.keySet()) {
threadPoolExecutor.execute(() -> {
try {
//业务逻辑
} catch (Exception e) {
log.error("线程池任务异常{}", e);
}
});
}
while (threadPoolExecutor.getQueue().size() > 0) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
threadPoolExecutor.shutdown();
try {
threadPoolExecutor.awaitTermination(360, TimeUnit.SECONDS);
} catch (Exception e) {
log.error("线程池超过3600秒未执行完成", e);
}
3.采用计数器
ExecutorService executor = Executors.newFixedThreadPool(10);
//定时计数器大小
final CountDownLatch latch = new CountDownLatch(images.length);
for (MultipartFile image : images) {
executor.submit(() -> {
try {
//业务逻辑
} catch (IOException e) {
}
latch.countDown();//当前线程调用此方法,则计数减一
});
}
try {
latch.await();//阻塞当前线程,直到计数器的值为0
executor.shutdown();
} catch (Exception e) {
}
本章结束,有不足之处,希望大佬多多指教