title: 线程池
category: Java
updatedAt: 2022-12-15T09:58:37.209Z
createdAt: 2022-12-15T09:37:21.958Z
线程池介绍:
Java里面线程池的顶级接口是java.util.concurrent.Executor
,以及他的子接口java.util.concurrent.ExecutorService
。
要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在java.util.concurrent.Executors
线程工厂类里面提供了一些静态工厂,生成一些常用的线程池。官方建议使用Executors工程类来创建线程池对象。
Executors类中有个创建线程池的方法如下:
public static ExecutorService newFixedThreadPool(int nThreads)
:返回线程池对象。(创建的是有界线程池,也就是池中的线程个数可以指定最大数量)
获取到了一个线程池ExecutorService 对象,那么怎么使用呢,在这里定义了一个使用线程池对象的方法如下:
-
public Future<?> submit(Runnable task)
:获取线程池中的某一个线程对象,并执行Future接口:用来记录线程任务执行完毕后产生的结果。
使用线程池中线程对象的步骤:
A:自定义一个类,作为任务类并实现Runnable接口;
B:实现Runnable接口中的run方法;
C:创建任务类的对象;
D:获取线程池对象;
E:直接执行任务;
需求:使用线程池来完成卖票任务。
//A:自定义一个类,作为任务类并实现Runnable接口;
class SellTicketTask implements Runnable
{
//定义成员变量存储100张票
private static int tickets=100;
//创建锁对象
private Lock l=new ReentrantLock();
//B:实现Runnable接口中的run方法;
public void run() {
// 模拟卖票
while(true)
{
//获取锁
l.lock();
if(tickets>0)
{
//休眠
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName()+"出票:"+tickets);
tickets--;
}
//释放锁
l.unlock();
}
}
}
-------
public class SellTicketDemo {
public static void main(String[] args) {
//C:创建任务类的对象;
SellTicketTask stt = new SellTicketTask();
//D:获取线程池对象; 获取2个线程
ExecutorService es = Executors.newFixedThreadPool(2);
//E:直接执行任务;
//自己创建线程对象的方式
// Thread t = new Thread(stt);
// t.start(); ---> 调用MyRunnable中的run()
// 从线程池中获取线程对象,然后调用SellTicketTask中的run()
es.submit(stt);
// 再获取个线程对象,调用SellTicketTask中的run()
es.submit(stt);
}
}
Callable测试代码:
<T> Future<T> submit(Callable<T> task)
: 获取线程池中的某一个线程对象,并执行.
/*
* 演示:演示Callable
* 我们忽略返回值,这个接口就与Runnable接口一样了
*/
class MyTask implements Callable<Object>{
@Override
public Object call() throws Exception {
for( int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + " ... " + i);
}
return null;
}
}
public class CallableDemo {
public static void main(String[] args) {
// 创建任务对象
MyTask mt = new MyTask();
// 获取线程池
ExecutorService es = Executors.newFixedThreadPool(2);
// 执行任务
es.submit(mt);
es.submit(mt);
}
}
问题2:Future
- 方法:
V get()
: 获取计算完成的结果。
A:我们自定义类,实现Callable接口
B:实现Call方法,Call方法有返回值
C:然后吧任务类对象交给线程池执行
D:执行完成的结果保存Future中
E:最后我们调用Future的get方法拿到真正的结果。
/*
* 演示:带返回值的线程任务
* 需求:通过Callable计算从1到任意数字的和
*/
class SumTask implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int sum = 0;
for(int i = 1; i <= 5; i++){
sum += i;
}
return sum ;
}
}
public class CallableDemo02 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 创建任务对象
SumTask st = new SumTask();
// 获取线程池
ExecutorService es = Executors.newFixedThreadPool(1);
// 执行任务
Future<Integer> future = es.submit(st);
// 等待运算结束,获取结果
Integer i = future.get();
System.out.println(i);
}
}
标签:Runnable,对象,接口,Callable,线程,public
From: https://www.cnblogs.com/yuan-autumn/p/17031436.html