CountDownLatch
闭锁。完成某些操作时,只有当其他所有线程都执行完毕,才继续执行当前运算。
private CountDownLatch latch;
public ThreadDemo(CountDownLatch latch){
this.latch = latch;
}
@Override
public void run() {
try {
// do something
}finally {
// 线程执行完毕必须要countDown
latch.countDown();
}
}
// 调用
public static void main(String[] args) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
new ThreadDemo(latch).start();
}
latch.await(); // 所有线程执行完毕后唤醒
System.out.println("执行完毕");
}
Callable
Callable接口搭配FutureTask也可以实现类似于闭锁CountDownLatch
Lock
**
* 用于解决多线程安全问题的方式:
* Syn
* 1.同步代码块
* 2.同步方法
* Lock
* 3.同步锁Lock:是一个显示锁,通过lock()上锁,通过unlock()方法解锁
* 必须将unlock放入finanlly代码块中,保证执行
**/
public class TestLock {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket).start();
new Thread(ticket).start();
new Thread(ticket).start();
}
}
class Ticket implements Runnable {
private int ticket = 100;
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (ticket > 0) {
lock.lock();
try {
Thread.sleep(200);
System.out.println(Thread.currentThread().getName()+"---"+ --ticket);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
Condition
/**
* Conditon线程通信:
* Syn: wait notify notifyAll
* Lock:await singal singalAll
**/
public class TestProductorAndConsumer {
public static void main(String[] args) {
Clerk clerk = new Clerk();
new Thread(new Productor(clerk)).start();
new Thread(new Consumer(clerk)).start();
}
}
// 店员
class Clerk {
private int product = 0;
private ReentrantLock lock = new ReentrantLock();
// 通过lock.newCondition获取锁
private Condition condition = lock.newCondition();
// 进货
public void get() {
lock.lock();
try {
// 为了避免虚假唤醒,此处应该使用while而不是if
while (product >= 1) {
System.out.println("产品已满");
try {
//this.wait();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " ---" + ++product);
//this.notifyAll();
condition.signalAll();
} finally {
lock.unlock();
}
}
// 卖货
public void sale() {
lock.lock();
try{
// 为了避免虚假唤醒,此处应该使用while而不是if
while (product <= 0) {
System.out.println("售罄");
try {
//this.wait();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "---" + --product);
//this.notifyAll();
condition.signalAll();
}finally {
lock.unlock();
}
}
}
class Productor implements Runnable {
private Clerk clerk;
public Productor(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
clerk.get();
}
}
}
class Consumer implements Runnable {
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
clerk.sale();
}
}
}
利用Condition循环打印ABC
/**
* 循环打印ABC
**/
public class TestABCAlternate {
public static void main(String[] args) {
final AlternameDemo demo = new AlternameDemo();
new Thread(()->{
while(true){
demo.loopA();
}
}).start();
new Thread(()->{
while(true){
demo.loopB();
}
}).start();
new Thread(()->{
while(true){
demo.loopC();
}
}).start();
}
}
class AlternameDemo{
private int number = 1;
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
public void loopA(){
lock.lock();
try{
if (number != 1){
condition1.await();
}
System.out.print("A");
number = 2;
condition2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void loopB(){
lock.lock();
try{
if (number != 2){
condition2.await();
}
System.out.print("B");
number = 3;
condition3.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void loopC(){
lock.lock();
try{
if (number != 3){
condition3.await();
}
System.out.print("C");
number = 1;
condition1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
ReadWriteLock
读写锁:
/**
* 读写锁
* 读不加锁,写加锁
* 写写/读写 互斥
* 读读 不互斥
**/
class ReadWriteLockDemo{
private int number = 0;
private ReadWriteLock lock = new ReentrantReadWriteLock();
// 读
public void get(){
lock.readLock().lock();
try{
System.out.println(Thread.currentThread().getName()+":"+number);
}finally {
lock.readLock().unlock();
}
}
public void set(int number){
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()+":"+number);
this.number = number;
}finally {
lock.writeLock().unlock();
}
}
}
线程锁
- 非静态方法的锁默认为this ,静态方法的锁默认为 Class对象
- 某一时刻内,只能有一个线程持有锁,无论几个方法
线程池
频繁的创建销毁线程很消耗资源。
-
线程池:提供一个线程队列,队列中保存着所有等待状态的线程。避免了创建与销毁额外开销,提高了响应速度
-
线程池的体系结构
-
工具类
ExecutorService newFixedThreadPool():创建固定大小的线程池
ExecutorService new CachedThreadPool():缓存线程池,线程池的数量不固定,可以根据需求自动更改数量
ExecutorService new SingleThreadExecutor():单个线程池。线程池中只有一个线程
线程调度:
ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 100; i++) {
Future<Integer> future = pool.schedule(new Callable<Integer>() {
@Override
public Integer call(){
int num = new Random().nextInt();
System.out.println(Thread.currentThread().getName() + " ---" +num);
return num;
}
},3, TimeUnit.SECONDS);
// 延迟3秒执行
System.out.println(future.get());
}
pool.shutdown();
分支合并框架
Fork/Join框架:将一个大任务拆分(fork)成若干个小任务(拆到不可拆分为止),再将一个个的小任务运算的结果进行汇总(join)。
class SumCalculate extends RecursiveTask<Long> {
private long start;
private long end;
// 临界值
private static final long THURSHOLD = 10000L;
public SumCalculate(long start, long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
long length = end -start;
if (length <= THURSHOLD){
long sum = 0L;
for (long i = start; i <= end; i++) {
sum += i;
}
return sum;
}else {
long middle = (start + end) /2;
SumCalculate left = new SumCalculate(start,middle);
left.fork();
SumCalculate right = new SumCalculate(middle+1,end);
right.fork();
return left.join()+right.join();
}
}
}
public static void main(String[] args) {
// 拆分需要ForkJoinPool的支持
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<Long> task = new SumCalculate(0L, 100000000L);
Long sum = pool.invoke(task);
System.out.println(sum);
}
Java8使用lambda表达式,更高的性能、更快的的速度、更高的cpu利用率:
Instant start = Instant.now();
Long sum = LongStream.rangeClosed(0L,500000000000L).parallel().reduce(0L,Long::sum);
System.out.println(sum);
Instant end = Instant.now();
System.out.println("耗费时间"+Duration.between(start,end).toMillis());