线程池:
线程容器,可设定线程分配的数量上限,将预先创建的对象存入池中,并重用线程池中的线程对象。避免频繁创建和销毁。
如图所示,线程池的容量是3,如果有四个线程需要运行,则最后一个任务需要等待其他线程的释放:
常用线程池接口和类:
jar包:java.util.concurrent
demo展示:
package com.test8;
import java.util.concurrent.*;
/**
* Executor:线程池的根接口:executor()
* 子接口ExecutorService:包含管理线程池的一些方法:如submit,shutdown
* 实现类:ThreadPoolExecutor
* 实现类:ScheduledThreadPoolExecutor
* Executors:创建线程池的工具类
* (1)newFixedThreadPool(int nThreads) : 创建固定线程数量的线程池
* (2)newCachedThreadPool() : 创建非固定数量的线程池
*
* 创建固定线程个数的线程池
* 创建缓存线程池,由任务的多少决定
* 创建单线程池
* 创建调度线程池,可按周期,定时执行
*/
public class ThreadDemo {
/**
* 创建个数为nThread个线程的线程池
*
* @param nThread 线程池里的线程个数
*/
public static void fixedThreadPool(int nThread) {
ExecutorService executorService = Executors.newFixedThreadPool(nThread);
Runnable runnable = createRunnable();
int n = 3;
// 提交n次,表示要运行n个线程
for(int i = 0; i < n; i++) {
executorService.submit(runnable);
}
// 等待所有任务执行完毕,再关闭线程池,即执行以前提交的任务,但是不接收新任务。
executorService.shutdown();
// shutdownNow则会试图停止所有正在执行的任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
// executorService.shutdownNow();
}
/**
* 创建缓存线程池,线程池中的线程个数不固定
*/
public static void cachedThreadPool() {
ExecutorService executorService = Executors.newCachedThreadPool();
Runnable runnable = createRunnable();
int n = 6;
// 提交n次,表示要运行n个线程
for(int i = 0; i < n; i++) {
executorService.submit(runnable);
}
// 等待所有任务执行完毕,再关闭线程池,即执行以前提交的任务,但是不接收新任务。
executorService.shutdown();
// shutdownNow则会试图停止所有正在执行的任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
// executorService.shutdownNow();
}
// 创建单个线程池
public static void singledThreadPool() {
// todo
}
// 创建调度线程池
public static void scheduledThreadPool() {
// todo
}
public static Runnable createRunnable() {
// 创建匿名内部类
Runnable runnable = new Runnable() {
private int ticket = 500;
@Override
public void run() {
while(true) {
synchronized (this.getClass()) {
if (ticket <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "卖了第" + ticket + "张票。");
ticket--;
}
}
}
};
return runnable;
}
public static void main(String[] args) {
// fixedThreadPool(4);
cachedThreadPool();
}
}
Callable在线程池中的应用:通过Future获取submit所返回的状态结果(call的返回值
),如果线程还没有执行完,则get方法会以zu'se一直等待。
package com.test10;
import java.util.concurrent.*;
public class Demo {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(1);
// 提交一个Callable任务,Future表示将要完成的任务的接口,可获取到将要返回的任务的结果
Future<Integer> Future = executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println( Thread.currentThread().getName() + "计算1到10的乘积:");
int sum = 1;
for (int i = 1; i <= 10; i++) {
sum *= i;
}
return sum;
}
});
// 获取结果,如果线程还没有返回结果,则get方法会一直等待
try {
Integer sum = Future.get();
System.out.println(sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
}
}
Lock同步锁:
1. ReentrantLock重入锁demo:
调用类:
package com.test12;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Ticket implements Runnable {
private int ticket = 100;
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
lock.lock();
try{
if (ticket <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "卖出了第" + ticket + "张票");
ticket--;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
lock.unlock();
}
}
}
}
主类:
package com.test12;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
ExecutorService executorService = Executors.newFixedThreadPool(8);
for (int i = 0; i < 4; i++) {
executorService.submit(ticket);
}
executorService.shutdown();
}
}