多线程与线程池

1.  java.util.concurrent(简称JUC )

在此包中增加了在并发编程中很常用的实用工具类,用于定义类似于线程的自定义子系统,包括线程池、异步IO 和轻量级任务框架。提供可调的、灵活的线程池。还提供了设计用于多线程上下文中的Collection 实现等

1.1 synchronized

  • 修饰普通方法,内置锁是当前类的实例;

  • 修饰静态方法,内置锁是当前类Class字节码对象,也就是 Xxx.class

  • 修饰静态代码块

1.2 生产者消费者案例

​
package com.isoftstone.mythread;

public class TestProductorAndConsumer {
	public static void main(String[] args) {
		Clerk clerk = new Clerk();
		Productor productor = new Productor(clerk);
		Consumer consumer = new Consumer(clerk);
		new Thread(productor,"生产者A").start();
		new Thread(productor,"生产者B").start();
		new Thread(consumer,"消费者a").start();
		new Thread(consumer,"消费者b").start();
	}
}
class Clerk {//店员
	private int product = 0;
	//进货
	public synchronized void get(){
		//这里不能使用if,避免虚假唤醒,应该总是使用在循环中
		while(product >= 10) {
			System.out.println("货物已满!");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName() + "--进货,货物个数变为"+ ++product);
		this.notifyAll();
	}
	//卖货
	public synchronized void sale(){
		//这里不能使用if,避免虚假唤醒,应该总是使用在循环中
		while(product <= 0) {
			System.out.println("货物为空!");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName() + "--卖货,货物个数变为"+ --product);
		this.notifyAll();
	}
}
class Productor implements Runnable {//生产者
	private Clerk clerk; //店员
	public Productor(Clerk clerk) {
		this.clerk = clerk;
	}
	public void run() {
		while(true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			clerk.get();
		}
	}
}
class Consumer implements Runnable {//消费者
	private Clerk clerk; //店员
	public Consumer(Clerk clerk) {
		this.clerk = clerk;
	}
	public void run() {
		while(true) {
			try {
				Thread.sleep(10009);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			clerk.sale();
		}
	}
}

1.3  volatile 内存可见性

  • 当一个线程修改了对象状态后,其他线程能够看到发生的状态变化

  • 不具备互斥性,也不能保证变量状态的“原子性操作”

1.4  原子变量 CAS算法

  • Compare And Swap   多线程情况下,假设原来的值是0,当最快的一个线程访问时候会查看这个值是否发生了变化,如果还是0,则值变为1;而对于第二名的线程过来时发现值已经改变,则会拿到这个值改变的值给自己,假设为1,继续下一轮的尝试;如果下一轮值没有变化,则值变为2;如果还是慢了,则继续拿到这个当前值进行下一轮的尝试

​
package com.isoftstone.mythread;
import java.util.concurrent.atomic.AtomicInteger;

public class TestAtomic {
	public static void main(String[] args) {
		AtomicDemo demo = new AtomicDemo();
		for (int i = 0; i < 30; i++) {
			new Thread(demo).start();
		}
	}
}
class AtomicDemo implements Runnable {
	//private volatile int serialNum = 0;
	private AtomicInteger serialNum = new AtomicInteger();

	public void run() {
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(getSerialNum());
		
	}

	public int getSerialNum() {
		//获取原来的值并且增加1
		return serialNum.getAndIncrement();
	}
}

 

1.5  ConcurrentHashMap 锁分段机制

内部采用“锁分段”机制替代Hashtable 的独占锁。进而提高性能

1.6  CopyOnWriteArrayList/CopyOnWriteArraySet

  • 写入并复制操作;

  • 添加操作多时,效率低,因为每次添加都要进行复制,开销很大;

  • 并发迭代操作多时可以选择

public static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();

1.7  CountDownLatch 闭锁

  • 确保某个计算在其需要的所有资源都被初始化之后才继续执行;

  • 确保某个服务在其依赖的所有其他服务都已经启动之后才启动;

  • 等待直到某个操作所有参与者都准备就绪再继续执行

​
package com.isoftstone.mythread;
import java.util.concurrent.CountDownLatch;

public class TestCountDownLatch {
	public static void main(String[] args) {
		int threadCount = 5;
		final CountDownLatch latch = new CountDownLatch(threadCount);
		LatchDemo demo = new LatchDemo(latch);
		long start = System.currentTimeMillis();
		for (int i = 0; i < threadCount; i++) {
			new Thread(demo).start();
		}
		try {
			latch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		long end = System.currentTimeMillis();
		System.out.println("耗费的时间=" + (end - start));
	}
}
class LatchDemo implements Runnable {
	private CountDownLatch latch;
	public LatchDemo(CountDownLatch latch) {
		this.latch = latch;
	}
	public void run() {
		synchronized (this) {
			try {
				for (int i = 0; i < 50000; i++) {
					if (i%2 == 0) {
						System.out.println(i);
					}
				}
			} catch (Exception e) {
				
			} finally {
				latch.countDown();
			}
		}
	}
}

 

1.8  Callable 接口

Callable 接口类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是Runnable 不会返回结果,并且无法抛出经过检查的异常。

​
package com.isoftstone.mythread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class TestCallable {
	public static void main(String[] args) {
		ThreadDemo demo = new ThreadDemo();
		FutureTask<Integer> task = new FutureTask<Integer>(demo);
		new Thread(task).start();
		try {
			//接收线程运算后的结果
			//只有线程都结束后才执行get方法,也就是说FutureTask可以用于闭锁
			Integer sum = task.get();
			System.out.println("sum="+sum);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
	}
}
class ThreadDemo implements Callable<Integer> {

	public Integer call() throws Exception {
		int sum = 0;
		for (int i = 0; i <= 100; i++) {
			sum += i;
		}
		return sum;
	}
}

 

1.9   Lock 同步锁

1.9.1 Lock版 卖票案例

​
package com.isoftstone.mythread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
	public static void main(String[] args) {
		Ticket ticket = new Ticket();
		new Thread(ticket,"1号窗口").start();
		new Thread(ticket,"2号窗口").start();
		new Thread(ticket,"3号窗口").start();
	}
}
class Ticket implements Runnable {
	private int tick = 100;
	private Lock myLock = new ReentrantLock();
	public void run() {
		while(true) {
			myLock.lock();
			try {
				if (tick > 0) {
					System.out.println(Thread.currentThread().getName() + "*****完成售票,余票=" + --tick);
				} else {
					return;
				}
			} catch (Exception e) {
			} finally {
				myLock.unlock();
			}	
		}
	};
}

 

1.9.2 Lock版 生产者消费者案例

​
package com.isoftstone.mythread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestProductAndConsumerWithLock {
	public static void main(String[] args) {
		Clerk clerk = new Clerk();
		Productor productor = new Productor(clerk);
		Consumer consumer = new Consumer(clerk);
		new Thread(productor,"生产者A").start();
		new Thread(productor,"生产者B").start();
		new Thread(consumer,"消费者a").start();
		new Thread(consumer,"消费者b").start();
	}
}
class Clerk {//店员
	private int product = 0;
	private Lock myLock = new ReentrantLock();
	private Condition myCondition = myLock.newCondition();//建立通信
	//进货
	public void get(){
		myLock.lock();
		try {
			//这里不能使用if,避免虚假唤醒,应该总是使用在循环中
			while(product >= 10) {
				System.out.println("货物已满!");
				try {
					myCondition.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.println(Thread.currentThread().getName() + "--进货,货物个数变为"+ ++product);
			myCondition.signalAll();
		} catch (Exception e) {
		} finally {
			myLock.unlock();
		}
		
	}
	//卖货
	public void sale(){
		myLock.lock();
		try {
			//这里不能使用if,避免虚假唤醒,应该总是使用在循环中
			while(product <= 0) {
				System.out.println("货物为空!");
				try {
					myCondition.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.println(Thread.currentThread().getName() + "--卖货,货物个数变为"+ --product);
			myCondition.signalAll();
		} catch (Exception e) {
		} finally {
			myLock.unlock();
		}
	}
}
class Productor implements Runnable {//生产者
	private Clerk clerk; //店员
	public Productor(Clerk clerk) {
		this.clerk = clerk;
	}
	public void run() {
		while(true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			clerk.get();
		}
	}
}
class Consumer implements Runnable {//消费者
	private Clerk clerk; //店员
	public Consumer(Clerk clerk) {
		this.clerk = clerk;
	}
	public void run() {
		while(true) {
			try {
				Thread.sleep(10009);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			clerk.sale();
		}
	}
}

 

1.9.3 Lock版 线程按序交替执行

​
package com.isoftstone.mythread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestABCAlternate {
	//编写程序
	//开启3个线程,这三个线程ID分别为A、B、C,
	//每个线程将自己的ID在屏幕打印10遍,
	//要求输出的结果必须按顺序显示,
	//如 ABCABCABCABCABCABCABCABCABCABC
	public static void main(String[] args) {
		AlternateDemo demo = new AlternateDemo();
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < 10; i++) {
					demo.loop1();
				}		
			}
		},"A").start();
		new Thread(new Runnable() {
					@Override
					public void run() {
						for (int i = 0; i < 10; i++) {
							demo.loop2();
						}	
					}
				},"B").start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < 10; i++) {
					demo.loop3();
				}		
			}
		},"C").start();
	}
}
class AlternateDemo {
	private int currThreadFlag = 1; //当前正在执行线程的标记
	private Lock myLock = new ReentrantLock();
	private Condition myCondition1 = myLock.newCondition();
	private Condition myCondition2 = myLock.newCondition();
	private Condition myCondition3 = myLock.newCondition();
	
	public void loop1() {
		myLock.lock();
		try {
			if (currThreadFlag != 1) {
				try {
					myCondition1.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.print(Thread.currentThread().getName());
			currThreadFlag = 2;
			myCondition2.signal();
		} catch (Exception e) {
		} finally {
			myLock.unlock();
		}
	}
	public void loop2() {
		myLock.lock();
		try {
			if (currThreadFlag != 2) {
				try {
					myCondition2.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.print(Thread.currentThread().getName());
			currThreadFlag = 3;
			myCondition3.signal();
		} catch (Exception e) {
		} finally {
			myLock.unlock();
		}
	}
	public void loop3() {
		myLock.lock();
		try {
			if (currThreadFlag != 3) {
				try {
					myCondition3.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.print(Thread.currentThread().getName());
			currThreadFlag = 1;
			myCondition1.signal();
		} catch (Exception e) {
		} finally {
			myLock.unlock();
		}
	}
}

 

1.10  读写锁 ReadWriteLock

  • ReadWriteLock 维护了一对相关的锁,一个用于只读操作, 另一个用于写入操作

  • 只要没有 writer,读取锁可以由 多个 reader 线程同时保持。写入锁是独占的

  • ReadWriteLock 读取操作通常不会改变共享资源,但执行 写入操作时,必须独占方式来获取锁

  • 对于读取操作占多数的数据结构。 ReadWriteLock 能提供比独占锁更高 的并发性

  • 而对于只读的数据结构,其中包含的不变性可以完全不需要考虑加锁操作

​
package com.isoftstone.mythread;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class TestReadWriteLock {
	public static void main(String[] args) {
		ReadWriteLockDemo demo = new ReadWriteLockDemo();
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				for (int i = 0; i < 20; i++) {
					if (i > 10) {
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					demo.read();
				}
			}
		},"Read").start();
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				demo.write("新的");
			}
		},"Write").start();
	}
}
class ReadWriteLockDemo {
	private String word = "原来";
	private ReadWriteLock myLock = new ReentrantReadWriteLock();
	public void read() {
		myLock.readLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + "读取内容:" + word);
		} catch (Exception e) {
		} finally {
			myLock.readLock().unlock();
		}
	}
	public void write(String word) {
		myLock.writeLock().lock();
		try {
			this.word = word;
			System.out.println(Thread.currentThread().getName() + "写入内容:" + word);
		} catch (Exception e) {
		} finally {
			myLock.writeLock().unlock();
		}
	}
}

 

1.11  线程八锁

  • 非静态方法的锁默认为this ;静态方法的锁为Class实例

  • 对于同一把锁而言,某一个时刻内,只能有一个线程持有这个锁,无论有几个方法

  • 锁不同,则互不影响;有锁与无锁也互不影响;

2  线程池

线程池提供了一个线程队列。队列中保存着所有等待状态的线程,避免创建与销毁的额外开销,提高了响应的速度。

2.1 线程池的体系结构

2.2 线程池的工具类Executors

2.2.1线程池分配多个任务,进行求和

​
package com.isoftstone.mythread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TestTheadPool {
	public static void main(String[] args) {
		//Executors.newFixedThreadPool(nThreads); //创建固定大小的线程池
		//Executors.newCachedThreadPool(); //创建缓存线程池,自动更改数量
		//Executors.newSingleThreadExecutor(); //创建单个线程
		ExecutorService executorService = Executors.newFixedThreadPool(5);
		
		//两个Callable接口实现类
		ThreadPoolDemo demo = new ThreadPoolDemo();
		ThreadPoolDemo2 demo2 = new ThreadPoolDemo2();
		
		//为线程池分配20个任务
		List<Future<Integer>> futureList = new ArrayList<>();
		for (int i = 0; i < 10; i++) {
			Future<Integer> future = executorService.submit(demo);
			futureList.add(future);
		}
		for (int i = 0; i < 10; i++) {
			Future<Integer> future = executorService.submit(demo2);
			futureList.add(future);
		}
		
		//归还到线程池
		executorService.shutdown();
		
		//遍历结果
		for (Future<Integer> future : futureList) {
			try {
				System.out.println(future.get());
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}
		}
	}

}
class ThreadPoolDemo implements Callable<Integer> {

	@Override
	public Integer call() throws Exception {
		int sum = 0;
		for (int i = 0; i <= 100; i++) {
			sum += i;
		}
		return sum;
	}
}
class ThreadPoolDemo2 implements 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;
	}
}

2.2.2 线程池的秒杀业务

package com.isoftstone.demo;

import java.util.concurrent.*;

public class MyTaskTest {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(30);
        for (int i = 1; i <= 200; i++) { //这里假设有200个人参与秒杀
            pool.submit(new MyTask("customer" + i));
        }
        pool.shutdown();
    }
}
class MyTask implements Runnable {
    private static int googsNum = 10; //商品初始数量
    private String customerName; //客户名称

    public MyTask(String customerName) {
        this.customerName = customerName;
    }

    @Override
    public void run() {
        String threadName = Thread.currentThread().getName();
        synchronized (MyTask.class) {
            if (googsNum > 0) {
                System.out.println(customerName + ",通过线程"+threadName+"抢到第"+googsNum+"个商品");
                googsNum--;
            } else {
                System.out.println(customerName + ",通过线程"+threadName+"秒杀任务失败。。。");
            }
        }
    }
}

2.2.3 线程池的ATM机取款业务

package com.isoftstone.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class MyATMTest {
    public static void main(String[] args) {
        //3台ATM机
        ExecutorService pool = Executors.newFixedThreadPool(3, new ThreadFactory() {
            private int id = 1;
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r,"ATM" + id++);
            }
        });
        for (int i = 0; i < 5; i++) { //5个取款用户取同一账号的钱
            pool.submit(new CustomerDemo("c-" + i,300));
        }
        pool.shutdown();
    }
}
class CustomerDemo implements Runnable {
    private static double total = 1000; //假设存入银行1000元
    private static double withdrawalAmount; //取款金额
    private String customerName; //客户名称

    public CustomerDemo(String customerName,double withdrawalAmount) {
        this.customerName = customerName;
        this.withdrawalAmount = withdrawalAmount;
    }

    @Override
    public void run() {
        String threadName = Thread.currentThread().getName();
        System.out.println(customerName + "开始准备取钱。。。");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (CustomerDemo.class) {
            if (total >= withdrawalAmount) {
                total -= withdrawalAmount;
                System.out.println(customerName +"通过取款机"+threadName+"取钱成功,余额=" + total);
            } else {
                System.out.println(customerName +"通过取款机"+threadName+"取钱失败,余额=" + total);
            }
        }
    }
}

2.3 线程池的调度

2.3.1 ScheduledExecutorService.schedule

​
package com.isoftstone.mythread;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class TestScheduledThreadPool {
	public static void main(String[] args) {
		ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
		try {
			for (int i = 0; i < 10; i++) {
				//每隔3秒执行一次,且可以有返回值
                                //如果当前线程的执行时间没有超过3秒,则按照间隔3秒执行下一次
				//如果当前线程的执行时间超过3秒,则按照当前线程执行时间算,执行完毕后,再开始下一次执行;
				ScheduledFuture<String> future = pool.schedule(new ScheduledDemo(i), 3, TimeUnit.SECONDS);
				System.out.println(future.get());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		pool.shutdown();
	}
}
class ScheduledDemo implements Callable<String> {
	private int id;
	public ScheduledDemo(int id) {
		this.id = id;
	}
	@Override
	public String call() throws Exception {
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//返回一个100以内的随机数
		return "当前线程名称=" + Thread.currentThread().getName() +",执行任务的ID="+id + ",所得的随机数="+new Random().nextInt(100);
	}
}

 

2.3.2 ScheduledExecutorService.scheduleAtFixedRate

​
package com.isoftstone.mythread;

import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class TestScheduledThreadPool2 {
	public static void main(String[] args) {
		ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
		try {
			//第一次运行从1/2/3秒后开始,然后后面每隔3秒执行一次,实例只能是实现Runnable接口
			//如果当前线程的执行时间没有超过3秒,则按照间隔3秒执行下一次
                        //如果当前线程的执行时间超过3秒,则按照当前线程执行时间算,执行完毕后,再开始下一次执行;
			pool.scheduleAtFixedRate(new ScheduledDemo2(1), 1,3, TimeUnit.SECONDS);
			//pool.scheduleAtFixedRate(new ScheduledDemo2(2), 2,3, TimeUnit.SECONDS);
			//pool.scheduleAtFixedRate(new ScheduledDemo2(3), 3,3, TimeUnit.SECONDS);
			//会优先打印over,因为上面三个线程是在1/2/3秒之后才第一次运行
			System.out.println("over");
			//int i = 1 / 0;
		} catch (Exception e) {
			e.printStackTrace();
			pool.shutdownNow();
		}
	}
}
class ScheduledDemo2 implements Runnable {
	private int id;
	public ScheduledDemo2(int id) {
		this.id = id;
	}

	@Override
	public void run() {
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("当前线程名称=" + Thread.currentThread().getName() +",执行任务的ID="+id + ",所得的随机数="+new Random().nextInt(100));
		
	}
}

2.3.3 ScheduledExecutorService.scheduleWithFixedDelay

​
package com.isoftstone.mythread;

import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class TestScheduledThreadPool3 {
	public static void main(String[] args) {
		ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
		try {
			//第一次运行从1/2/3秒后开始,然后后面延迟3秒执行一次,实例只能是实现Runnable接口
			//只能等当前线程完成后,且延迟3秒,才执行下一次
			pool.scheduleWithFixedDelay(new ScheduledDemo2(1), 1,3, TimeUnit.SECONDS);
			//pool.scheduleWithFixedDelay(new ScheduledDemo2(2), 2,3, TimeUnit.SECONDS);
			//pool.scheduleWithFixedDelay(new ScheduledDemo2(3), 3,3, TimeUnit.SECONDS);
			//会优先打印over,因为上面三个线程是在1/2/3秒之后才第一次运行
			System.out.println("over");
			//int i = 1 / 0;
		} catch (Exception e) {
			e.printStackTrace();
			pool.shutdownNow();
		}
	}
}
class ScheduledDemo3 implements Runnable {
	private int id;
	public ScheduledDemo3(int id) {
		this.id = id;
	}

	@Override
	public void run() {
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("当前线程名称=" + Thread.currentThread().getName() +",执行任务的ID="+id + ",所得的随机数="+new Random().nextInt(100));
		
	}
}

​

 

3.  Java8并行流

java8并行流底层其实就是在JDK1.7时就有的Fork/Join框架,但是写起来太麻烦,Java8进行了优化

3.1 for循环遍历求和

​
package com.isoftstone.mythread;

import java.time.Duration;
import java.time.Instant;
import java.util.stream.LongStream;

import org.junit.jupiter.api.Test;

public class TestJDK8 {
	@Test
	public void testJdk8() {
                //java8新特性  572毫秒  parallel()并行
		Instant start = Instant.now();
		long sum = LongStream.rangeClosed(0L, 5000000000L)
				  .parallel()
				  .reduce(0L,Long::sum);
		System.out.println(sum);
		Instant end = Instant.now();
		System.out.println("jdk8耗费时间为:" + Duration.between(start, end).toMillis());
	}
	
	@Test
	public void testNormal() {//普通for循环 1441毫秒
		Instant start = Instant.now();
		long sum = 0;
		for (long i = 0; i < 5000000000L; i++) {
			sum += i;
		}
		System.out.println(sum);
		Instant end = Instant.now();
		System.out.println("normal耗费时间为:" + Duration.between(start, end).toMillis());
	}
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱梦君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值