JUC笔记(使用)

JUC笔记(使用)

三、使用

线程创建和使用

	// 第四种:使用线程池来创建线程
    @Test
    public void test04(){
        ExecutorService service = new ThreadPoolExecutor(
                2,
                Runtime.getRuntime().availableProcessors(),
                2,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3)
        );
        for (int i = 0; i < 10; i++) {
            service.submit(()->{
                System.out.println(Thread.currentThread().getName());
            });
        }

        service.shutdown();
    }

    // 第三种:实现Callable接口来实现线程创建 : 可以有返回值、进行管理
    @Test
    public void test03() throws ExecutionException, InterruptedException {
        class Test03 implements Callable<String> {
            @Override
            public String call() {
                return "1";
            }
        }
        Test03 test03 = new Test03();
        FutureTask<String> ft=new FutureTask<>(test03);
        //FutureTask实现了Runnable接口所以可以传入
        Thread t=new Thread(ft);
        t.start();
        System.out.println(ft.get());
    }

    // 第二种:实现Runable接口来实现线程创建
    @Test
    public void test02(){
        class Test02 implements Runnable{
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println("执行了run方法");
                }
            }
        }
        new Thread(new Test02()).start();
    }

    // 第一种:继承Thread类来实现线程创建
    @Test
    public void test01(){
        class Test01 extends Thread{
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println("执行了run方法");
                }
            }
        }
        new Test01().start();
    }

volatile关键字的使用

public class Demo01 {
    private static volatile int num = 0;

    // 三、禁止指令重排

    /**
     * 指令重排:程序运行时的样子不是你所理想型的样子,在不影响程序结果的前提下,指令执行的顺序可以进行调换。
     *
     * 初始化参数:a、b、x、y都为0
     * 指令重排前的样子:
     * 线程A:x = a;b = 1;
     * 线程B:y = b;a = 2;
     * 结果:x = 0;y = 0;
     *
     * 指令重排后的样子:
     * 线程A:b = 1;x = a;
     * 线程B:a = 2;y = b;
     * 结果:x = 2;y = 1;
     *
     */

    // 使用AtomicInteger保持原子性
    AtomicInteger atomicInteger = new AtomicInteger(0);
    // 二、不保持原子性
    @Test
    public void test02(){
        for (int i = 0; i < 10; i++) {
            new Thread(()->num++).start();
        }
        System.out.println(num);
        // 保持原子性
        for (int i = 0; i < 10; i++) {
            new Thread(()->atomicInteger.getAndIncrement()).start();
        }

        while (Thread.activeCount()>2){
            Thread.yield();
        }
        System.out.println(atomicInteger.get());

    }

    // 一、保持可见性

    /**
     * 线程有单独的工作内存
     */
    @Test
    public void test01(){
        new Thread(()-> {while(num == 0){}}).start();
        num++;
        System.out.println(num);
    }
}

Lock锁的使用

// 生产者与消费者
public class Demo01 {
    public static void main(String[] args){
        ProductionAndConsumption pac = new ProductionAndConsumption();
        for (int i = 0; i < 10; i++) {
            new Thread(()->pac.getNumber()).start();
        }
        for (int i = 10; i < 20; i++) {
            new Thread(()->pac.setNumber()).start();
        }

    }
}
class ProductionAndConsumption{
    private int number = 0;

    public Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    public void setNumber(){
        lock.lock();
        try{
            while (number == 1){
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.printf(Thread.currentThread().getName()+"\t生产\t库存: %s\n",++number);
            condition.signalAll();
        }catch(Exception e){
           e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void getNumber(){
        lock.lock();
        try{
            while (number == 0){
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.printf(Thread.currentThread().getName()+"\t消费\t\t库存: %s\n",--number);
            condition.signalAll();
        }catch(Exception e){
           e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
//		synchronized方式
//    public synchronized void setNumber(){
//        while (number == 1){
//            try {
//                wait();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        }
//        System.out.printf(Thread.currentThread().getName()+"\t生产\t库存: %s\n",++number);
//        notifyAll();
//    }
//
//    public synchronized void getNumber(){
//        while (number == 0){
//            try {
//                wait();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        }
//        System.out.printf(Thread.currentThread().getName()+"\t消费\t\t库存: %s\n",--number);
//        notifyAll();
//    }
}

ForkJoin的使用

public class SumTask extends RecursiveTask<Long> {
    public static void main(String[] args){
        // 创建随机数组成的数组:
        long[] array = new long[400];
        for (int i = 0; i < array.length; i++) {
            array[i] = new Random().nextInt(1000);
        }
        // fork/join task:
        ForkJoinPool fjp = new ForkJoinPool(4); // 最大并发数4
        ForkJoinTask<Long> task = new SumTask(array, 0, array.length);
        long startTime = System.currentTimeMillis();
        Long result = fjp.invoke(task);
        long endTime = System.currentTimeMillis();
        System.out.println("Fork/join sum: " + result + " in " + (endTime - startTime) + " ms.");
    }

    static final int THRESHOLD = 100;
    long[] array;
    int start;
    int end;

    SumTask(long[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        if (end - start <= THRESHOLD) {
            // 如果任务足够小,直接计算:
            long sum = 0;
            for (int i = start; i < end; i++) {
                sum += array[i];
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            System.out.println(String.format("compute %d~%d = %d", start, end, sum));
            return sum;
        }
        // 任务太大,一分为二:
        int middle = (end + start) / 2;
        System.out.println(String.format("split %d~%d ==> %d~%d, %d~%d", start, end, start, middle, middle, end));
        SumTask subtask1 = new SumTask(this.array, start, middle);
        SumTask subtask2 = new SumTask(this.array, middle, end);
        invokeAll(subtask1, subtask2);
        Long subresult1 = subtask1.join();
        Long subresult2 = subtask2.join();
        Long result = subresult1 + subresult2;
        System.out.println("result = " + subresult1 + " + " + subresult2 + " ==> " + result);
        return result;
    }
}
### 关于JUC (Java Util Concurrency) 的概述 并发编程中的同步机制对于多线程环境下的数据一致性至关重要。`ConcurrentHashMap` 是 `Hashtable` 和 `synchronizedMap` 的替代品,在高并发场景下性能更好[^2]。 #### ConcurrentHashMap的工作原理 在 JDK 1.7 中,`ConcurrentHashMap` 使用分段数组加链表的方式存储键值对,并通过 `ReentrantLock` 锁定整个哈希桶数组的一部分来控制并发访问;而在 JDK 1.8 及之后版本里,则采用了类似于 `HashMap` 的设计——即当遇到哈希碰撞时采用链表或者红黑树结构保存溢出的数据项,不过不同之处在于其利用 CAS 操作以及 Synchronizer 来确保线程安全性的同时提高了并行度。 #### 原子操作与锁优化 原子变量类提供了无锁定且高效的算法实现方式,比如 `AtomicInteger`, `AtomicLong` 等可以用于计数器等简单数值更新场合。此外还有诸如读写锁(`ReadWriteLock`)、信号量(`Semaphore`)等一系列工具可以帮助开发者更好地处理复杂的业务逻辑需求。 #### 弱引用的应用 除了上述内容外,在某些特殊情况下可能还会涉及到对象生命周期管理方面的话题,例如使用弱引用来追踪那些不再被强引用指向但仍可作为缓存使用的实例。需要注意的是,这类对象会在下次垃圾收集过程中被清理掉[^3]。 ```java import java.util.concurrent.locks.ReentrantLock; // 创建一个显式的重入锁 final ReentrantLock lock = new ReentrantLock(); lock.lock(); // 获取锁 try { // 访问共享资源... } finally { lock.unlock(); // 释放锁 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值