JUC笔记

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();
        }
    }
}

线程锁


  1. 非静态方法的锁默认为this ,静态方法的锁默认为 Class对象
  2. 某一时刻内,只能有一个线程持有锁,无论几个方法

线程池


频繁的创建销毁线程很消耗资源。

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

  2. 线程池的体系结构
    在这里插入图片描述

  3. 工具类

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());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值