三、 执行器
(1) 简介:
- 用于启动并控制线程的执行
- 核心接口Executor,包含一个execute(Runnable)用于指定被执行的线程
- ExecutorService接口用于控制线程执行和管理线程
- 预定义了如下执行器:ThreadPoolExecutor、ScheduledThreadPoolExecutor、ForkJoinPool
(2)Callable和Future接口在执行器中的使用
- Callable<V>
:表示具有返回值的线程,V:表示返回值类型
- call():执行任务
- Future<V>
:表示Callable的返回值, V:返回值类型
- get():获取返回值
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ESDemo {
public static void main(String[] args)throws Exception{
ExecutorService es = Executors.newFixedThreadPool(2);
Future<Integer> r1 = es.submit(new MC(1,100));
Future<Integer> r2 = es.submit(new MC(100,10000));
System.out.println(r1.get()+":"+r2.get());
es.shutdown();
}
}
class MC implements Callable<Integer>{
private int begin,end;
public MC(int begin,int end){
this.begin = begin;
this.end = end;
}
@Override
public Integer call() throws Exception {
// TODO Auto-generated method stub
int sum = 0;
for(int i=begin;i<end;i++){
sum +=i;
}
return sum;
}
}
四、 锁和原子操作
(1)java.util.concurrent.locks包中提供了对锁的支持。锁的作用是为使用synchronized控制对资源访问提供了替代机制。基本操作模型:访问资源之前申请锁,访问完毕之后释放锁。
- lock/tryLock:申请锁
- unlock:释放锁
- Lock是一个接口,具体锁类ReentrantLock实现了Lock接口
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockDemo {
public static void main(String[] args){
new MT().start();
new MT().start();
new MT().start();
new MT().start();
}
}
class Data{
static int i=0;
// static synchronized void operate(){
// i++;
// System.out.println(i);
// }
//创建锁,代替synchronized
static Lock lock = new ReentrantLock();
static void operate(){
lock.lock();//申请锁
i++;
System.out.println(i);
lock.unlock();//释放锁
}
}
class MT extends Thread{
public void run(){
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Data.operate();
}
}
}
(2) java.util.concurrent.atom包中提供了对原子操作的支持,原子操作主要是提供了不需要锁以及其他同步机制就可以进行的一些不可中断操作。通过原子操作,能够简化对锁的一些控制。主要操作为:获取、设置、比较等。
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockDemo {
public static void main(String[] args){
new MT().start();
new MT().start();
new MT().start();
new MT().start();
}
}
class Data{
static int i=0;
// static synchronized void operate(){
// i++;
// System.out.println(i);
// }
//创建锁,代替synchronized
// static Lock lock = new ReentrantLock();
// static void operate(){
// lock.lock();//申请锁
// i++;
// System.out.println(i);
// lock.unlock();//释放锁
// }
static AtomicInteger ai = new AtomicInteger(0);
static void operate(){
System.out.println(ai.incrementAndGet());
}
}
class MT extends Thread{
public void run(){
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Data.operate();
}
}
}
五、 流编程(JDK8 中新加入的支持并行编程的流 API )
(1) 流的基本知识:流表示数据的移动,在移动过程中可能会对数据进行处理,这个流不同于io流,它表示流对象。
流的操作分为中间操作和终端操作。中间操作会产生一个新流,终端操作会消费流。
(2)流的编程模型:
- 获取流:stream/parallelSteam(获取串行流/或并行流)
- 操作:sort/max/min/…
(3) 流的基本操作
- 过滤、排序、缩减、映射、收集、迭代
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
//需要在jdk1.8环境下
public class StreamDemo {
public static void main(String[] args){
List<String> ls = new ArrayList<>();
ls.add("abc");
ls.add("def");
ls.add("ddd");
ls.add("eee");
ls.add("def");
ls.add("cba");
// Optional<String> max = ls.stream().max(String::compareTo);
// System.out.println(max.get());//获取集合中字典序的最大元素
//集合中元素按照字典序升序排列
ls.stream().sorted().forEach(e -> System.out.println(e));//集合中元素按照字典序升序排列
//获取不重复元素的个数
ls.stream().distinct().count();
}
}
六、 Fork/Join框架
(1)Fork/Join框架中的主要类:
- ForkJoinTask<V>
:描述任务的抽象类
- ForkJoinPool:管理ForkJoinTask的线程池
- RecursiveAction:ForkJoinTask子类,描述无返回值的任务
- RecursiveTask<V>
:ForkJoinTask子类,描述有返回值的任务
(2) 分而治之策略
- 将任务递归划分成更小的子任务,直到子任务足够小,从而能够被连续地处理掉为止。
- 优势是处理过程可以使用并行发生,这种情况特别适合基于多核处理器的并行编程
- 根据Java API中定义,分而治之的建议临界点定义在100-1000个操作中的某个位置
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
public class ForkJoinDemo {
public static void main(String[] args) throws Exception{
ForkJoinPool forkJoinPool = new ForkJoinPool();
//计算0到1000000的和
Future<Long> result = forkJoinPool.submit(new MTask(0,1000001));
System.out.println(result.get());
forkJoinPool.shutdown();
}
}
class MTask extends RecursiveTask<Long> {
static final int THRESNOLD = 1000;
private int begin,end;
public MTask(int begin,int end){
this.begin = begin;
this.end = end;
}
@Override
protected Long compute() {
// TODO Auto-generated method stub
long sum = 0;
if((end-begin)<=THRESNOLD){
for(int i=begin;i<end;i++){
sum +=i;
}
}else{
int mid = (begin+end)/2;
MTask left = new MTask(begin,mid);
left.fork();
MTask right = new MTask(mid+1,end);
right.fork();
Long lr = left.join();
System.out.println(begin+"-"+mid+":"+lr);
Long rr = right.join();
System.out.println((mid+1)+"-"+end+":"+rr);
sum = lr+rr;
}
return sum;
}
}