常用线程池接口和类
线程池
- 线程容器,可设定线程分配的数量上限。
- 将预先创建的线程对象存入池中,并重用线程池中的线程对象。
- 避免频繁的创建和销毁。
常用线程池接口和类(所在包java.util.concurrent):
-
Executor: 线程池顶级接口。
-
ExecutorService:线程池接口,可通过submit(Runnable task)提交任务。
-
Executors工具类:通过此类可以获得一个线程池。
-
通过newFixedThreadPool(int nThreads):获取固定数量的线程池。参数:指定线程池中线程的数量。
-
newCashedThreadPool():获得动态数量的线程池,如不够则重新创建新的,没有上限。
-
代码实现
package com.sun.base.XianCheng;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 演示线程池的创建
* Executor :线程池的根接口,executor()
* ExecutorService:包含管理线程池的一些方法,submit、shutdown
* ThreadPoolExecutor
* ScheduledThreadPoolExecutor
* Executors:创建线程池的工具类
* (1)创建固定线程个数线程池
* (2)创建动态线程池
* (3)创建单线程池
* (4)创建调度线程池 调度:周期、定时执行
*/
public class Demo01 {
public static void main(String[] args){
//创建固定个数的线程池
// ExecutorService es=Executors.newFixedThreadPool(5);
//创建动态线程池
ExecutorService es=Executors.newCachedThreadPool();
//创建单线程线程池
//Executors.newSingleThreadExecutor();
//创建调度线程池
//Executors.newScheduledThreadPool();
// 创建任务
Runnable runnable=new Runnable() {
private int ticket=100;
@Override
public void run() {
while (true){
if (ticket<=0){
break;
}
System.out.println(Thread.currentThread().getName()+"卖了第"+ticket+"张票");
ticket--;
}
}
};
//提交任务
for (int i =0;i<5;i++){//5=上面的线程池个数
es.submit(runnable);
}
//关闭线程池
es.shutdown();
}
}
-
Callable接口
public interface Callable
public V call() throws Exception;
}
-1、与Runnable接口类似,实现之后代表一个接口任务。
-2、Callable具有泛型返回值、可以声明异常。
```java
package com.sun.base.XianCheng;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* 演示Callable接口的使用
* Callable与Runnable接口的区别:
* 1、Callable中call方法具有泛型返回值、Runnable接口中run方法没有返回值
* 2、Callable中call方法可以声明异常,Runnable接口中run方法没有异常
*/
public class Demo02 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//功能需求,使用Callable实现1-100的和
//1、创建Callable对象
Callable<Integer> callable=new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"开始计算");
int sum=0;
for (int i=0;i<=100;i++){
sum+=i;
}
return sum;
}
};
//把Callable对象转成任务
FutureTask<Integer> task=new FutureTask<>(callable);
//创建线程
Thread thread=new Thread(task);
thread.start();
//获取结果
Integer sum = task.get();
System.out.println("计算结果是:"+sum);
}
}
-
Future接口
- Future:表示将要完成任务的结果。
-
线程池+Callable接口+Future+接口的综合使用
package com.sun.base.XianCheng;
import java.util.concurrent.*;
/**
* 要求:计算1-100的和
* 使用两个线程,并发计算1-50、51-100的和,再进行汇总统计。
*/
public class Demo03 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建线程池
ExecutorService es = Executors.newFixedThreadPool(2);
//提交任务
Future<Integer> future=es.submit(new Callable<Integer>() {
private int sum=0;
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"开始计算");
for (int i=0;i<=50;i++){
sum+=i;
}
return sum;
}
});
Future<Integer> future2=es.submit(new Callable<Integer>() {
private int sum=0;
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"开始计算");
for (int i=51;i<=100;i++){
sum+=i;
}
return sum;
}
});
//汇总
int sum=future.get()+future2.get();
System.out.println("计算结果是:"+sum);
}
}
-
线程同步(单条执行路径)
- 形容一次方法调用,同步一旦开始,调用者必须等待该方法返回,才能继续。(只要有等待就是同步)
-
线程异步(多条执行路径)
- 形容一次方法调用,异步一旦开始,像是一次消息传递,调用者告知之后立刻返回。二者竞争时间片,并发执行。
-
Lock接口
-
与synchronized比较,显示定义,结构更灵活。
-
提供更多实用性方法,功能更强大、性能更优越。
-
常用方法:
void lock() //获取锁,如锁被占用,则等待。
boolean tryLock() //尝试获取锁(成功返回true,失败返回false,不阻塞)。
void unlock() //释放锁。
-
重入锁
ReentrantLock:Lock接口的实现类,与synchronized一样具有互斥锁功能。
Lock lock=new ReentrantLock; ... lock.lock();//上锁 try{ ... }finally{ lock.unlock();//释放锁 } -
读写锁ReentrantReadWriteLock
一种支持一写多读的同步锁,读写分离,可分别分配读锁、写锁。
支持多次分配读锁,使多个读操作可以并发执行。
互斥规则:
- 写-写:互斥,阻塞。
- 读-写:互斥,读阻塞写,写阻塞读。
- 读-读:不互斥,不阻塞。
- 在读操作远远高于写操作的环境下,可在保障线程安全的情况下,提高运行效率。
-
ReentrantReadWriteLock rwl=new ReentrantReadWriteLock();//创建读写锁
ReadLock readLock= rwl.readLock();//获得读锁
WriteLock writeLock= rwl.writeLock();//获得写锁

浙公网安备 33010602011771号