juc工具类

线程池

介绍

增减时机

keepAlive 和线程工厂

线程池用法

线程池特点

停止线程池

任务前后执行(可暂停的线程池)

public class PausePool extends ThreadPoolExecutor {
​
    public PausePool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }
​
    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        lock.lock();
        try {
            while (isPaused){
                unpaused.await();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
​
    private boolean isPaused;
    ReentrantLock lock = new ReentrantLock();
    private Condition unpaused = lock.newCondition();
    private void pause(){
        lock.lock();
        try {
            isPaused = true;
        } finally {
            lock.unlock();
        }
    }
    public void resume(){
        lock.lock();
        try {
            isPaused = false;
            unpaused.signalAll();
        }finally {
            lock.unlock();
        }
    }
​
    public static void main(String[] args) throws InterruptedException {
        PausePool pausePool = new PausePool(10,20,101,TimeUnit.SECONDS,
                new LinkedBlockingDeque<>());
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("执行");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        for (int i = 0; i < 10000; i++) {
            pausePool.execute(runnable);
        }
        Thread.sleep(1500);
        pausePool.pause();
        System.out.println("pause");
        Thread.sleep(1500);
        pausePool.resume();
        System.out.println("start");
    }
}

线程池原理

线程池任务复用:相同线程执行不同任务

线程池状态

ThreadLocal

使用场景

场景1

/**
 * 描述:     利用ThreadLocal,给每个线程分配自己的dateFormat对象,保证了线程安全,高效利用内存
 */
public class ThreadLocalNormalUsage05 {
​
    public static ExecutorService threadPool = Executors.newFixedThreadPool(10);
​
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 1000; i++) {
            int finalI = i;
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    String date = new ThreadLocalNormalUsage05().date(finalI);
                    System.out.println(date);
                }
            });
        }
        threadPool.shutdown();
    }
​
    public String date(int seconds) {
        //参数的单位是毫秒,从1970.1.1 00:00:00 GMT计时
        Date date = new Date(1000 * seconds);
//        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat dateFormat = ThreadSafeFormatter.dateFormatThreadLocal.get();
        return dateFormat.format(date);
    }
}
​
class ThreadSafeFormatter {
    public static ThreadLocal<SimpleDateFormat>
    dateFormatThreadLocal = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        }
    };
​
}

场景2

public class ThreadTest {
    public static void main(String[] args) {
        new Service1().process();
    }
}
class Service1{
    public void process(){
        User user = new User("test");
        UserHolder.holder.set(user);
        new Service2().process();
    }
}
class Service2{
    public void process(){
        System.out.println(UserHolder.holder.get());
        new Service3().process();
    }
}
class Service3{
    public void process(){
        System.out.println(UserHolder.holder.get());
​
    }
}
class  UserHolder{
    public static ThreadLocal<User> holder = new ThreadLocal<>();
}
class User{
    String  name;
    public User(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

总结

两个作用:

1、让需要用到的对象在线程捡隔离,每个线程都有自己的独立的对象

2、在任何方法中都可以轻松获取到该对象

根据对象生成实际不同选择不同而方法

1、initialvalue

在Threadlocal第一次get的时候把对象初始化出来,对象的初始化时机由我们控制

2、set

如果需要保存到threadlocal里的对象的生成时机不被我们控制,用set放到threadlocal中去。

原理

方法

ThreadLocalMap

注意点

内存泄漏

空指针

直接返回基本类型long,会因为拆箱装箱将Null转化为Long空指针异常

public class ThreadPoolNPE {
   ThreadLocal<Long> threadLocal =  new ThreadLocal<Long>();
   void set(){
       threadLocal.set(Thread.currentThread().getId());
​
   }
    
   Long get(){
       return threadLocal.get();
   }
​
    public static void main(String[] args) {
        ThreadPoolNPE threadPoolNPE = new ThreadPoolNPE();
        System.out.println(threadPoolNPE.get());
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                threadPoolNPE.set();
//                System.out.println(threadPoolNPE.get());
//            }
//        }).start();
    }
}

lock

public class LockInterruptibly implements Runnable {
​
    private Lock lock = new ReentrantLock();
public static void main(String[] args) {
    LockInterruptibly lockInterruptibly = new LockInterruptibly();
    Thread thread0 = new Thread(lockInterruptibly);
    Thread thread1 = new Thread(lockInterruptibly);
    thread0.start();
    thread1.start();
​
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    thread1.interrupt();
}
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "尝试获取锁");
        try {
            lock.lockInterruptibly();
            try {
                System.out.println(Thread.currentThread().getName() + "获取到了锁");
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + "睡眠期间被中断了");
            } finally {
                lock.unlock();
                System.out.println(Thread.currentThread().getName() + "释放了锁");
            }
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + "获得锁期间被中断了");
        }
    }
}

可见性

锁分类

乐观锁和悲观锁

重入锁

例子:预定电影院座位

public class SeatLock {
    static ReentrantLock lock = new ReentrantLock();
    static void bookSeat(){
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+"开始预定");
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName()+"预定完成");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
​
    public static void main(String[] args) {
        new Thread(()->bookSeat()).start();
        new Thread(()->bookSeat()).start();
        new Thread(()->bookSeat()).start();
    }
}

性质源码

public class ReentrantLockTest {
    static ReentrantLock lock = new ReentrantLock();
​
    public static void access() {
        lock.lock();
        try {
            System.out.println("处理");
            if (lock.getHoldCount() < 5){
                System.out.println(lock.getHoldCount());
                access();
                System.out.println(lock.getHoldCount());
            }
        }finally {
            lock.unlock();
        }
    }
​
    public static void main(String[] args) {
        access();
    }
}

公平锁

避免唤醒带来的空档期

/**
 * 描述:     演示公平和不公平两种情况
 */
public class FairLock {
​
    public static void main(String[] args) {
        PrintQueue printQueue = new PrintQueue();
        Thread thread[] = new Thread[10];
        for (int i = 0; i < 10; i++) {
            thread[i] = new Thread(new Job(printQueue));
        }
        for (int i = 0; i < 10; i++) {
            thread[i].start();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
​
class Job implements Runnable {
​
    PrintQueue printQueue;
​
    public Job(PrintQueue printQueue) {
        this.printQueue = printQueue;
    }
​
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "开始打印");
        printQueue.printJob(new Object());
        System.out.println(Thread.currentThread().getName() + "打印完毕");
    }
}
​
class PrintQueue {
​
    private Lock queueLock = new ReentrantLock(true);
​
    public void printJob(Object document) {
        queueLock.lock();
        try {
            int duration = new Random().nextInt(10) + 1;
            System.out.println(Thread.currentThread().getName() + "第一次正在打印,需要" + duration);
            Thread.sleep(duration * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            queueLock.unlock();
        }
​
        queueLock.lock();
        try {
            int duration = new Random().nextInt(10) + 1;
            System.out.println(Thread.currentThread().getName() + "第二次正在打印,需要" + duration+"秒");
            Thread.sleep(duration * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            queueLock.unlock();
        }
    }
}

共享锁和排他锁

public class ReadWriteLock {
    private static ReentrantReadWriteLock reentrantReadWriteLock
             = new ReentrantReadWriteLock();
    private static ReentrantReadWriteLock.ReadLock readLock
     = reentrantReadWriteLock.readLock();
    private static ReentrantReadWriteLock.WriteLock writeLock
            = reentrantReadWriteLock.writeLock();
    private static void read(){
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+"读");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            System.out.println(Thread.currentThread().getName()+"释放读");
            readLock.unlock();
        }
    }
    private static void write(){
        writeLock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+"写");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            System.out.println(Thread.currentThread().getName()+"释放写");
            writeLock.unlock();
        }
    }

    public static void main(String[] args) {
        new Thread(ReadWriteLock::read, "t1").start();
        new Thread(ReadWriteLock::read, "t2").start();
        new Thread(ReadWriteLock::write, "t3").start();
        new Thread(ReadWriteLock::write, "t4").start();
    }
}

总结:只能降级,不能升级,适合读多写少的场合

自旋和阻塞

可中断锁

原子类

public class AtomicInteger1 implements Runnable{
    private static final AtomicInteger ato
             = new AtomicInteger();
    private static final AtomicInteger ato1
            = new AtomicInteger();
    void incre(){
        ato.getAndIncrement();
        ato1.getAndAdd(2);
    }
    static volatile int basicCount = 0;
    void increBasic(){
        basicCount++;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            incre();
            increBasic();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        AtomicInteger1 r = new AtomicInteger1();
        Thread thread = new Thread(r);
        Thread thread1 = new Thread(r);
        thread.start();
        thread1.start();
        Thread.sleep(1000);
        System.out.println(ato.get());
        System.out.println(ato1.get());
        System.out.println(basicCount);
    }
}

数组和引用

class Dece implements Runnable{
    private AtomicIntegerArray array;

    public Dece(AtomicIntegerArray array) {
        this.array = array;
    }

    @Override
    public void run() {
        for (int i = 0; i < array.length(); i++) {
            array.getAndDecrement(i);
        }
    }
}
class Ince implements Runnable{
    private AtomicIntegerArray array;

    public Ince(AtomicIntegerArray array) {
        this.array = array;
    }

    @Override
    public void run() {
//        for (int i = 0; i < array.length(); i++) {
//            array.getAndIncrement(i);
//        }
    }
}
public class AtomicInteger2 {


    public static void main(String[] args) throws InterruptedException {
        AtomicIntegerArray array = new AtomicIntegerArray(1000);
        Ince ince = new Ince(array);
        Dece dece = new Dece(array);
        Thread[] threads2 = new Thread[10];
        Thread[] threads1 = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads1[i] = new Thread(dece);
            threads2[i] = new Thread(ince);
            threads1[i].start();
            threads2[i].start();
        }
        for (int i = 0; i < 10; i++) {

            threads1[i].join();
            threads2[i].join();
        }
        for (int i = 0; i < array.length(); i++) {
//            if (array.get(i) != 0){
//                System.out.println("error"+i);
//            }
            System.out.println(array.get(i));
        }
        System.out.println("success");

    }
}

升级原子类

public class AtomiciUpdate implements Runnable{
    static Candidate tom;
    static Candidate peter;
    static AtomicIntegerFieldUpdater<Candidate> sco
             = AtomicIntegerFieldUpdater.newUpdater(Candidate.class, "score");

    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            peter.score++;
            sco.getAndIncrement(tom);
        }
    }

    public static class Candidate{
        volatile int score;
    }

    public static void main(String[] args) throws InterruptedException {
        tom = new Candidate();
        peter = new Candidate();
        AtomiciUpdate atomiciUpdate = new AtomiciUpdate();
        new Thread(atomiciUpdate).start();
        new Thread(atomiciUpdate).start();
        Thread.sleep(1000);
        System.out.println(tom.score);
        System.out.println(peter.score);
    }
}

Adder累加器

CAS

public class CASTest implements Runnable
{
    private volatile int value;
    synchronized int compareAndSwap(int expect, int newValue){
        int old = value;
        if (old == expect){
            value = newValue;
        }
        return old;
    }

    public static void main(String[] args) throws InterruptedException {
        CASTest r = new CASTest();
        r.value = 0;
        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(r.value);
    }

    @Override
    public void run() {
        compareAndSwap(0, 1);
    }
}

不变性

final

并发容器

map

concurrenthashmap

为什么把1.7的结构改为1.8?

数据结构不同,提高了并发性,

hash碰撞,8有红黑树

并发安全,7segment,lock,8 cas+syn

复杂度,7链表n,8红黑树logn

为什么超过8转为红黑树:默认链表,占用内存更少,想要达到8概率很低

组合操作线程不安全:replace方法

copyonwriteArrayList

add方法用lock加锁

阻塞队列

ArrayBlockingQueue
有界,容量限制
put方法Lock锁
LinkedBlockingQueue
无界,容量为最大值
Put方法lock锁和原子类锁

并发流程

countdown

//多等1
public class CountDownTest {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(5);
        ExecutorService service = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 5; i++) {
            final int n = i+1;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                        System.out.println(n+"end");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        latch.countDown();
                    }
                }
            };
            service.submit(runnable);
        }
        System.out.println("start");
        latch.await();
        System.out.println("all end");
    }
}
// 多等1
public class CountDownTest2 {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        ExecutorService service = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 5; i++) {
            final int n = i+1;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println(n+"wait");
                    try {
                        latch.await();
                        System.out.println(n+"start");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            };
            service.submit(runnable);
        }
        Thread.sleep(500);
        System.out.println("can");
        latch.countDown();
    }
}
//多等一和一等多结合
public class CountDownTest3 {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        CountDownLatch count = new CountDownLatch(5);
        ExecutorService service = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 5; i++) {
            final int n = i+1;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println(n+"等待跑");
                    try {
                        latch.await();
                        System.out.println(n+"开始跑");
                        Thread.sleep(new Random().nextInt(1000));
                        System.out.println(n+"到终点");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        count.countDown();
                    }

                }
            };
            service.submit(runnable);
        }
        Thread.sleep(500);
        System.out.println("比赛开始");
        latch.countDown();
        count.await();
        System.out.println("所有都到了");
    }
}

信号量

condition

public class Conditiontest {
    private ReentrantLock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    void method1() throws InterruptedException {
        lock.lock();
        try {
            System.out.println("wait");
            condition.await();
            System.out.println("start");
        } finally {
            lock.unlock();
        }
    }
    void method2() throws InterruptedException {
        lock.lock();
        try {
            System.out.println("complete");
            condition.signal();

        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Conditiontest r1 = new Conditiontest();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    r1.method2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        r1.method1();
    }
}

生产消费者案例:

/**
 * 描述:     演示用Condition实现生产者消费者模式
 */
public class ConditionDemo2 {

    private int queueSize = 10;
    private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();

    public static void main(String[] args) {
        ConditionDemo2 conditionDemo2 = new ConditionDemo2();
        Producer producer = conditionDemo2.new Producer();
        Consumer consumer = conditionDemo2.new Consumer();
        producer.start();
        consumer.start();
    }

    class Consumer extends Thread {

        @Override
        public void run() {
            consume();
        }

        private void consume() {
            while (true) {
                lock.lock();
                try {
                    while (queue.size() == 0) {
                        System.out.println("队列空,等待数据");
                        try {
                            notEmpty.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.poll();
                    notFull.signalAll();
                    System.out.println("从队列里取走了一个数据,队列剩余" + queue.size() + "个元素");
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    class Producer extends Thread {

        @Override
        public void run() {
            produce();
        }

        private void produce() {
            while (true) {
                lock.lock();
                try {
                    while (queue.size() == queueSize) {
                        System.out.println("队列满,等待有空余");
                        try {
                            notFull.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.offer(1);
                    notEmpty.signalAll();
                    System.out.println("向队列插入了一个元素,队列剩余空间" + (queueSize - queue.size()));
                } finally {
                    lock.unlock();
                }
            }
        }
    }

}

循环栅栏

AQS

future callable

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值