线程和进程
进程:一个程序、QQ.exe程序的集合
一个进程通常包含多个线程
线程有几个状态
- New 新生
- RUNNABLE 运行
- BLOCKED 阻塞
- WAITTING 等待
- TIMED_WAITTING 超时等待
- TERMINATED 终止
wait/sleep的区别
1、来自不同的类
wait => Object
sleep => Thread
2、关于锁的释放
wait 会释放锁,sleep 不会释放锁
3、使用范围是不同的
wait必须在同步代码块中
sleep可以在任何地方使用
4、是否需要捕获异常
wait不需要捕获异常
sleep需要捕获异常
Lock锁 和Synchronized
- Synchronized 是一个内置的关键字,Lock是一个Java类
- Synchonized无法获取锁的状态,Lock锁是可以获取锁的状态
- Synchonized 会自动施法锁,Lock需要手动释放锁,不释放会死锁
- Synchonized 会产生阻塞;Lock锁不会一直等待
- Synchonized 可重入锁,不可以中断,非公平的;Lock 可重入锁。可以判断锁。默认非公平的(可以自己设置)
- Synchonized 适合锁少量的同步代码,Lock锁适合锁大量的同步代码
锁是什么?如果判断锁是谁?
第一种情况:一个对象,两个synchronized方法,锁的是对象,因为用了同一个对象,所以用的是用一把锁,谁先拿到锁,就谁先执行
输出:
sendSms
call
package juc;
import java.util.concurrent.TimeUnit;
public class lock8 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
// synchronized 锁的对象是方法的调用者
// 两个方法用的是同一个锁,谁先拿到谁先执行
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendSms");
}
public synchronized void call(){
System.out.println("call");
}
}
**第二种情况:**两个不同的对象,两个synchronized 方法,因为是两个对象,synchronized 锁的是不同的对象,所以没有公用一把锁。因此先输出call后输出sendsms
package juc;
import java.util.concurrent.TimeUnit;
public class lock8 {
public static void main(String[] args) {
Phone phone = new Phone();
Phone phone1 = new Phone();
new Thread(()->{
phone.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone1.call();
},"B").start();
}
}
class Phone{
// synchronized 锁的对象是方法的调用者
// 两个方法用的是同一个锁,谁先拿到谁先执行
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendSms");
}
public synchronized void call(){
System.out.println("call");
}
}
**第三种情况:**同一个对象,一个synchronized同步方法,和一个普通方法,由于一个是普通方法,根本没上锁,所以锁只是锁了sendSms,所以会先执行hello,sendSms sleep了时间
package juc;
import java.util.concurrent.TimeUnit;
public class lock8 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.hello();
},"B").start();
}
}
class Phone{
// synchronized 锁的对象是方法的调用者
// 两个方法用的是同一个锁,谁先拿到谁先执行
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendSms");
}
public synchronized void call(){
System.out.println("call");
}
public void hello(){
System.out.println("hello");
}
}
**第四种情况:**两个静态的同步方法,一个对象,静态的同步方法,锁的是class模板,所以用的是同一个锁,谁先拿到锁谁先输出
package juc;
import java.util.concurrent.TimeUnit;
public class LockStatic {
public static void main(String[] args) {
Phone2 phone2=new Phone2();
// Phone2 phone21=new Phone2();
new Thread(()->{
phone2.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
// new Thread(()->{
// phone2.hello();
// },"C").start();
}
}
class Phone2{
// synchronized 锁的对象是方法的调用者
// 两个方法用的是同一个锁,谁先拿到谁先执行
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendSms");
}
public static synchronized void call(){
System.out.println("call");
}
public void hello(){
System.out.println("hello");
}
}
第五种情况:一个静态的同步方法,一个普通的同步方法,两个对象
因为静态同步方法锁的是class模板 ,而普通的同步方法锁的是对象,因此锁的是不同的,所以会先输出call
package juc;
import java.util.concurrent.TimeUnit;
public class LockStatic {
public static void main(String[] args) {
Phone2 phone2=new Phone2();
Phone2 phone21=new Phone2();
new Thread(()->{
phone2.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone21.call();
},"B").start();
// new Thread(()->{
// phone2.hello();
// },"C").start();
}
}
class Phone2{
// synchronized 锁的对象是方法的调用者
// 两个方法用的是同一个锁,谁先拿到谁先执行
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendSms");
}
public synchronized void call(){
System.out.println("call");
}
public void hello(){
System.out.println("hello");
}
}
集合类不安全
ArrayList 是线程不安全的
解决方案1:把ArrayList改成线程安全的 Collections.synchronizedList
解决方案2: 使用CopyOnWriteArrayList线程安全
package juc;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class Test04 {
public static void main(String[] args) {
// 线程不安全的
// 解决方案1 List<String> arrayList = Collections.synchronizedList(new ArrayList<>()); 把arraylist搞成线程安全的
// 解決方案2 :List<String> arrayList =new CopyOnWriteArrayList<>();
// List<String> arrayList = Collections.synchronizedList(new ArrayList<>());
List<String> arrayList =new CopyOnWriteArrayList<>();
// ConcurrentModificationException 并发修改异常,在多线程的条件下,ArrayList是线程不安全的
// List<String> arrayList =new ArrayList<>() ;
for (int i = 0; i <30 ; i++) {
new Thread(()->{
arrayList.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(arrayList);
},String.valueOf(i)).start();
}
}
}
HashSet
和List是同样的解决方案
解决方案1:把HashSet改成线程安全的 Collections.synchronizedList
解决方案2: 使用CopyOnWriteArraySet线程安全
Map
Map不安全的,
使用ConcurrentHashMap线程安全的
package juc;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class MapTest {
public static void main(String[] args) {
// 会产生ConcurrentModificationException 并发修改异常
// Map<String,String> hashMap = new HashMap<>();
ConcurrentHashMap<String,String> hashMap = new ConcurrentHashMap<>();
for (int i = 1; i <50 ; i++) {
new Thread(()->{
hashMap.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,5));
System.out.println(hashMap);
},String.valueOf(i)).start();
}
}
}
常用的辅助类
countDownLatch(减法计数器)
package juc;
import java.util.concurrent.CountDownLatch;
public class countDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
// 总是是6,必须要执行任务的时候,在使用
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"GO");
countDownLatch.countDown(); //数量减1
},String.valueOf(i)).start();
}
countDownLatch.await(); //等待计数器归0
System.out.println("close");
}
}
原理:countDownLatch.countDown() countDownLatch.await();
cyclicBarrier(加法计数器)
package juc;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
System.out.println("成功");
});
for (int i = 1; i <=7; i++) {
final int temp=i;
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"拿了"+temp+"个");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
原理: cyclicBarrier.await();
Semaphore(做限流比较多)
package juc;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreDemo {
public static void main(String[] args) {
// 线程数量
Semaphore semaphoreDemo = new Semaphore(3);
for (int i = 1; i <= 6; i++) {
new Thread(()->{
try {
semaphoreDemo.acquire();
System.out.println(Thread.currentThread().getName()+"抢到车位");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphoreDemo.release();
}
},String.valueOf(i)).start();
}
}
}
原理: semaphoreDemo.acquire(); 得到锁 semaphoreDemo.release(); 释放锁
ReadWriteLock
package juc;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/***
独占锁(写锁) 一次只能被一个线程占有
共享锁(读锁) 多个线程可以同时占有
读-读 可以共存
写-写 不可以共存
读-写 不可以共存
***/
public class ReentrantReadWriteLockDemo {
public static void main(String[] args) {
MyCacheLock myCache = new MyCacheLock();
// MyCache myCache2 = new MyCache();
for (int i = 1; i < 5; i++) {
final int temp=i;
new Thread(()->{
myCache.put(temp+"",temp+"");
},String.valueOf(i)).start();
}
for (int i = 1; i < 5; i++) {
final int temp=i;
new Thread(()->{
myCache.get(temp+"");
},String.valueOf(i)).start();
}
}
}
class MyCacheLock{
private volatile Map<String,Object> map =new HashMap<>();
// 读写锁:更加细粒度的控制
private ReadWriteLock lock=new ReentrantReadWriteLock();
//存
public void put(String key,Object value){
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()+"写入"+key);
map.put(key,value);
System.out.println(Thread.currentThread().getName()+"写入完毕");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.writeLock().unlock();
}
}
//取
public void get(String key){
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()+"读取"+key);
map.get(key);
System.out.println(Thread.currentThread().getName()+"读取OK");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.readLock().unlock();
}
}
}
/**
* 自定义缓存
*/
class MyCache{
private volatile Map<String,Object> map =new HashMap<>();
//存
public void put(String key,Object value){
System.out.println(Thread.currentThread().getName()+"写入"+key);
map.put(key,value);
System.out.println(Thread.currentThread().getName()+"写入完毕");
}
//取
public void get(String key){
System.out.println(Thread.currentThread().getName()+"读取"+key);
map.get(key);
System.out.println(Thread.currentThread().getName()+"读取OK");
}
}
阻塞队列 BlockingQueue
使用队列
方式 | 抛出异常 | 不抛出异常 | 阻塞等待 | 超时等待 |
---|---|---|---|---|
添加 | add | offer | put | offer(value, 超时时间,超时时间单位) |
删除 | remove | poll | take | poll(超时时间,超时时间单位) |
package juc;
import java.util.Collection;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class BlockingQueueDemo {
public static void main(String[] args) throws InterruptedException {
test3();
}
/**
* 抛出异常
*/
public static void test1(){
ArrayBlockingQueue blockingQueue =new ArrayBlockingQueue<>(3);
blockingQueue.add("a");
blockingQueue.add("b");
blockingQueue.add("c");
//.IllegalStateException: Queue full 抛出异常
// System.out.println(blockingQueue.add("d"));
blockingQueue.remove();
blockingQueue.remove();
blockingQueue.remove();
// NoSuchElementException
// System.out.println(blockingQueue.remove());
}
/**
* 有返回值,不抛出异常
*/
public static void test2(){
ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(3);
// 往队列中加值
arrayBlockingQueue.offer("a");
arrayBlockingQueue.offer("a");
arrayBlockingQueue.offer("a");
// 不抛出异常 返回 false
System.out.println(arrayBlockingQueue.offer("a"));
// 往队列中去拿值
arrayBlockingQueue.poll();
arrayBlockingQueue.poll();
arrayBlockingQueue.poll();
// 不抛出异常 返回null
System.out.println(arrayBlockingQueue.poll());
}
/**
* 阻塞等待
*/
public static void test3() throws InterruptedException {
ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(3);
arrayBlockingQueue.put("a");
arrayBlockingQueue.put("a");
arrayBlockingQueue.put("a");
// arrayBlockingQueue.put("a"); //会一直死死的等待
arrayBlockingQueue.take();
arrayBlockingQueue.take();
arrayBlockingQueue.take();
// System.out.println(arrayBlockingQueue.take());//也会死死的等待取
}
/**
* 超时等待
*/
public void test4() throws InterruptedException {
ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(3);
arrayBlockingQueue.offer("a");
arrayBlockingQueue.offer("a");
arrayBlockingQueue.offer("a");
arrayBlockingQueue.offer("a",2,TimeUnit.SECONDS);//设定超时2秒,结束等待
arrayBlockingQueue.poll();
arrayBlockingQueue.poll();
arrayBlockingQueue.poll();
arrayBlockingQueue.poll(2,TimeUnit.SECONDS);//设定超时2秒,结束等待,等待2秒后就不会取
}
}
SynchronousQueue 同步队列
同步队列没有容量,只能往里面存一个元素,等下取,取完才能再次存下一个元素
线程池
池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我
线程池的好处
1: 、降低资源的消耗
2:提高响应的速度
3:方便管理
Executors 工具类 3大方法
package juc;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class PoolDemo {
public static void main(String[] args) {
// ExecutorService executorService = Executors.newSingleThreadExecutor();//单个线程
// ExecutorService executorService = Executors.newFixedThreadPool(5);//创建一个固定线程池的大小
ExecutorService executorService = Executors.newCachedThreadPool();//可伸缩的
try {
for (int i = 0; i <100 ; i++) {
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 线程池用完,程序结束,关闭线程池
executorService.shutdown();
}
}
}
本质3大方法都是调用了ThreadPool,7大参数
public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
int maximumPoolSize, //最大核心线程池的大小
long keepAliveTime, //超时了没有调用就释放
TimeUnit unit, //超时单位
BlockingQueue<Runnable> workQueue, // 阻塞队列
ThreadFactory threadFactory, //线程工厂:创建线程一般不用动
RejectedExecutionHandler handler // 拒绝策略) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
自定义线程池
package juc;
import java.util.concurrent.*;
/***
* new ThreadPoolExecutor.AbortPolicy() //银行满了,还有人进来,不处理这个人,抛出异常
* new ThreadPoolExecutor.CallerRunsPolicy() //哪里来的,回哪里 。本示例上会交给main方法执行
* new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常
* new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,会和最早的线程去竞争一下,不会抛出异常
*/
public class PoolDemo {
public static void main(String[] args) {
// ExecutorService executorService = Executors.newSingleThreadExecutor();//单个线程
// ExecutorService executorService = Executors.newFixedThreadPool(5);//创建一个固定线程池的大小
// ExecutorService executorService = Executors.newCachedThreadPool();//可伸缩的
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
try {
for (int i = 0; i <100 ; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 线程池用完,程序结束,关闭线程池
threadPoolExecutor.shutdown();
}
}
}
四种拒绝策略
new ThreadPoolExecutor.AbortPolicy() //银行满了,还有人进来,不处理这个人,抛出异常 new ThreadPoolExecutor.CallerRunsPolicy() //哪里来的,回哪里 。本示例上会交给main方法执行 new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常 new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,会和最早的线程去竞争一下,不会抛出异常
最大的线程的大小如何定义
1:cpu密集型:几核就是几,可以保持cpu的效率最高
2:IO 密集型 。判断你程序中十分耗IO 的线程,高于这个线程数就可以了
cpu密集型示例代码
package juc;
import java.util.concurrent.*;
/***
* new ThreadPoolExecutor.AbortPolicy() //银行满了,还有人进来,不处理这个人,抛出异常
* new ThreadPoolExecutor.CallerRunsPolicy() //哪里来的,回哪里 。本示例上会交给main方法执行
* new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常
* new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,会和最早的线程去竞争一下,不会抛出异常
*/
public class PoolDemo {
public static void main(String[] args) {
System.out.println(Runtime.getRuntime().availableProcessors());
// ExecutorService executorService = Executors.newSingleThreadExecutor();//单个线程
// ExecutorService executorService = Executors.newFixedThreadPool(5);//创建一个固定线程池的大小
// ExecutorService executorService = Executors.newCachedThreadPool();//可伸缩的
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
2,
Runtime.getRuntime().availableProcessors(),
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
try {
for (int i = 0; i <100 ; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 线程池用完,程序结束,关闭线程池
threadPoolExecutor.shutdown();
}
}
}
四大函数式接口(必须掌握) 作用:简化编程模型
函数式接口:只有一个参数,有一个输出
package juc;
import java.util.function.Function;
/**
* Function 函数型接口,有一个输入参数,有一个输出
* 只要是函数式接口,都可以用lambda表达式简化
*/
public class FunctionTest {
public static void main(String[] args) {
// Function function = new Function<String,String>() {
// @Override
// public String apply(String s) {
// return s;
// }
// };
Function function1=(str)->{return str;};
System.out.println(function1.apply("ssss"));
}
}
断定型接口(predicate):有一个输入参数,返回值是布尔值
/**
* Predicate 断定型接口:有一个输入参数,返回值只能死布尔值
*/
public class PredicateTest {
public static void main(String[] args) {
// Predicate<String> stringPredicate = new Predicate<String>() {
// @Override
// public boolean test(String s) {
// return false;
// }
// };
Predicate<String> stringPredicate=(str)->{return false;};
System.out.println(stringPredicate.test("test"));
}
}
Consumer消费型接口:有一个输入参数,但是没有返回值
package juc;
import java.util.function.Consumer;
/**
* 消费型接口:有一个输入参数,没有返回值
*/
public class ConsumerTest {
public static void main(String[] args) {
// Consumer<String> stringConsumer = new Consumer<>() {
// @Override
// public void accept(String s) {
// System.out.println(s);
// }
// };
Consumer<String> stringConsumer=(str)->{return;};
stringConsumer.accept("test2");
}
}
Supplier 供集型接口: 没有参数,只有返回值
package juc;
import java.util.function.Supplier;
/**
* supplier 供集型接口:没有参数,只有返回值
*/
public class SupplierTest {
public static void main(String[] args) {
// Supplier<Integer> integerSupplier = new Supplier<>() {
// @Override
// public Integer get() {
// return 1024;
// }
// };
Supplier<Integer> integerSupplier=()->{return 1024;};
System.out.println(integerSupplier.get());
}
}
Stream 流式计算
什么是Stream流式计算
package juc;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
/**
* 题目要求:一分钟内完成此题,只能用一行代码实现
* 现在有5个用户!
* 1:ID必须是偶数
* 2.年龄必须大于23岁
* 3,用户名转为大写字母
* 4,用户名字母倒着排序
* 5.只输出一个用户
*/
public class StreamTest {
public static void main(String[] args) {
User u1=new User(1,"a",21);
User u2=new User(2,"b",22);
User u3=new User(3,"c",23);
User u4=new User(4,"d",24);
User u5=new User(6,"e",25);
// 集合就是存储
List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
// 计算交给流
list.stream().filter(u->{return u.getId()%2==0;})
.filter(u->{return u.getAge()>23;})
.map(u->{return u.getName().toUpperCase();})
.sorted((uu1,uu2)->{return uu2.compareTo(uu1);})
.limit(1)
.forEach(System.out::println);
}
}
class User {
private int id;
private String name;
private int age;
public User() {
}
public User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
ForkJoin
什么是Forkjoin
Forkjoin在JDK1.7,并行执行任务,提高效率,大数据量
Forkjoin特点:工作窃取(a任务完成了,会窃取b 任务未完成的任务)
package juc;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
public class TestForkJoin {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// test1(); //12274
test3(); //328
}
public static void test1(){
Long sum=0L;
long start=System.currentTimeMillis();
for (Long i = 1L; i <10_0000_0000 ; i++) {
sum+=i;
}
Long end=System.currentTimeMillis();
System.out.println("sum="+sum+"时间:"+(end-start));
}
public static void test2() throws ExecutionException, InterruptedException {
Long start=System.currentTimeMillis();
ForkJoinPool forkJoinPool =new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinTest(0L, 10_0000_0000L);
ForkJoinTask<Long> submit = forkJoinPool.submit(task);
submit.get();
Long end=System.currentTimeMillis();
System.out.println("时间:"+(end-start));
}
public static void test3(){
Long start=System.currentTimeMillis();
//Stream并行流
LongStream.rangeClosed(0L,10_0000_0000L).parallel().reduce(0,Long::sum);
Long end=System.currentTimeMillis();
System.out.println("时间:"+(end-start));
}
}