java使用多线程的三种方式:
- 继承Thread类,并重写run方法。
- 实现Runnable接口,重写run方法
- 实现Callable<返回值>接口,重写call方法
java使用线程池实现多线程:
创建线程池
new ThreadPoolExecutor(参数一:核心线程数,参数2:最大线程数,参数3:最大容量);
在这段代码中,使用了 ThreadPoolExecutor 来创建一个线程池,并且设置了核心线程数为7,最大线程数为14,工作队列为容量为100的 LinkedBlockingDeque,拒绝策略为 CallerRunsPolicy。
// 创建线程池
private static final ThreadPoolExecutor THREAD_POOL = new ThreadPoolExecutor(
7, 14, 0,
TimeUnit.SECONDS, new LinkedBlockingDeque<>(100),
Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
多线程使用方式:
static ReentrantLock lock = new ReentrantLock();
public void thread() {
// 参数为线程的数量 如开了两条线程 就设置为2
CountDownLatch countDownLatch = new CountDownLatch(2);
// 线程一
THREAD_POOL.execute(() -> {
try {
执行代码逻辑
// 同步锁 如需要集合新增操作 在lock的lock()方法和unlocak()方法中进行实现 避免不必要的风险
lock.lock();
list.add();
lock.unlock();
} catch (Exception e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
// 在finally块中在释放锁是为了避免在try中还没执行到释放锁的时候报错从而释放失败
if (lock.isLocked()) {
lock.unlock();
}
}
});
// 线程2
THREAD_POOL.execute(() -> {
try {
执行代码逻辑
lock.lock();
lock.unlock();
} catch (Exception e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
if (lock.isLocked()) {
lock.unlock();
}
}
});
// 如还需同步执行代码逻辑 复制上方代码在try块中编写代码逻辑
try {
// 举例 开了两条线程 await超时时间设置为1秒 如果这两条线程执行1秒还没有执行完毕 就
// 立即结束线程并返回 如果有返回对象 而返回的对象还未执行到赋值阶段 则最终返回
// null
boolean await = countDownLatch.await(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
当调用 unlock() 方法时,如果当前线程并没有持有该锁,会抛出 IllegalMonitorStateException 异常,因此在正常情况下无需手动检查锁的状态再进行解锁操作。
使用了 ReentrantLock 来实现线程同步,确保对共享资源的访问是线程安全的
代码中使用了 CountDownLatch 来等待多个线程执行完成,但在 await 方法中传入的超时时间为 3 秒,可能会导致在某些情况下无法等待所有线程执行完成。建议根据。实际需求仔细考虑等待超时的设置。