JUC

进程与线程。

对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。

有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。

由于每个进程至少要干一件事,所以,一个进程至少有一个线程。当然,像Word这种复杂的进程可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。当然,真正地同时执行多线程需要多核CPU才可能实现。

Java默认有两个线程,Main线程和GC线程。

Java本身其实是不能开启线程的,当我们调用线程的start()方法时候,其实底层调用的是下面的方法(C++方法)

private native void start0();

并发与并行

并发:针对的是单核CPU。(CPU在同一时间只能处理一个任务)所谓并发,就是通过一种算法将 CPU 资源合理地分配给多个任务,当一个任务执行 I/O 操作时,CPU 可以转而执行其它的任务,等到 I/O 操作完成以后,或者新的任务遇到 I/O 操作时,CPU 再回到原来的任务继续执行。

并行:针对多核CPU。(多个线程可以同时执行)多核 CPU 的每个核心都可以独立地执行一个任务,而且多个核心之间不会相互干扰。在不同核心上执行的多个任务,是真正地同时运行,这种状态就叫做并行。

并发编程的本质:充分利用CPU资源。

线程的状态

Thread.State 该枚举类定义了线程的集中状态。

public enum State {
    /**
     * 线程新生
     */
    NEW,
    /**
     * 运行状态
     */
    RUNNABLE,

    /**
     * 阻塞状态(线程阻塞于锁)
     */
    BLOCKED,

    /**
     * 等待状态(一直等)
     */
    WAITING,

    /**
     * 指定了等待时间的等待状态(超时等待,过期不候)
     */
    TIMED_WAITING,

    /**
     * 已终止线程的线程状态。线程已完成执行。
     */
    TERMINATED;
}

线程状态演示代码

run()和start()

run()只是普通的方法调用,有主线程执行代码,并没有开启新线程。

start() 新开辟线程执行。起到了多线程异步的效果。

sleep()和wait()

wait() 属于Object.java、会释放锁、只能在同步代码块中使用(因为他需要锁)

sleep()属于Thread.java、不会释放锁、可以在任何地方使用。

sleep小妙用防止cpu占用达到100%

避免while(true)空转浪费CPU资源

while(true){
	try {
		Thread.sleep(50);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
}

sleep() 和 yield()

sleep():

调用sleep()会让当前线程从RUNNABLE状态进入TIMED_WAITING状态。

其他线程可以使用interrupt()方法打断正在睡眠的线程,这是sleep发放会抛出异常(InterrupteException)。

睡眠结束后线程未必会立刻得到执行。

建议使用TimeUnit 的 sleep 代替Thread的sleep 获取更好的可读性。

线程打断演示代码

yield()

调用yield()方法 让线程从RUNNING(java线程并没有running状态,此处只表示线程正在执行)状态到RUNNABLE状态,然后cpu调度其他同优先级的线程,要是没有其他线程可调用,不能保证实现线程暂停的效果。

具体的实现依赖于操作系统的任务调度器。

扩展优雅停止线程-两阶段终止模式

synchronized 和 Lock

synchronized 是内置关键字;Lock是接口。

synchronized 无法判断获取锁的状态;Lock可以判断是否获取到锁。

synchronized 自动释放锁;Lock需要手动释放锁。

synchronized 线程1(获得锁,阻塞),线程2(等待,一直等);Lock不一定一直等tryLock()方法尝试获取锁。

synchronized 可重入锁,不可中断的,非公平;Lock 可重入锁,可以判断锁,非公平(可自己设置)。

synchronized 适合锁少量的代码同步问题;Lock 适合锁大量的代码同步问题。

生产者消费者

传统:

class Data {
    private int data = 0;

    public synchronized void increment() throws InterruptedException {
        //此处用while 解决虚假唤醒问题,不能用if(if 只执行一次)
        while (data != 0) {
            //等待
            this.wait();
        }
        data++;
        System.out.println(Thread.currentThread().getName() + "-->+1--结果---" + data);
        //通知其他线程+1完成
        this.notifyAll();
    }

    public synchronized void decrement() throws InterruptedException {
        //此处用while 解决虚假唤醒问题,不能用if
        while (data == 0) {
            //等待
            this.wait();
        }
        data--;
        System.out.println(Thread.currentThread().getName() + "-->-1--结果---" + data);
        //通知其他线程-1完成
        this.notifyAll();
    }
}
public class ProductAndConsumer {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"C").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"D").start();
    }
}
class Data2 {
    private int data = 0;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    public  void increment() {
        lock.lock();
        try {
            //此处用while 解决虚假唤醒问题,不能用if(if 只执行一次)
            while (data != 0) {
                //等待
                condition.await();
            }
            data++;
            System.out.println(Thread.currentThread().getName() + "-->+1--结果---" + data);
            //通知其他线程+1完成
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public  void decrement() {
        lock.lock();
        try {
            //此处用while 解决虚假唤醒问题,不能用if
            while (data == 0) {
                //等待
                condition.await();
            }
            data--;
            System.out.println(Thread.currentThread().getName() + "-->-1--结果---" + data);
            //通知其他线程-1完成
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

线程顺序执行

/**
 * 让三个线程顺序执行:A->B->C  (精确通知)
 */
class Data3 {
    private int data = 1;
    Lock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();
    Condition condition3 = lock.newCondition();

    public void printA() throws InterruptedException {
        lock.lock();
        try {
            while (data != 1) {
                //等待
                condition1.await();
            }
            System.out.println(Thread.currentThread().getName() + "printA---data = " + data);
            data = 2;
            condition2.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printB() throws InterruptedException {
        lock.lock();
        try {
            while (data != 2) {
                //等待
                condition2.await();
            }
            System.out.println(Thread.currentThread().getName() + "printB---data = " + data);
            data = 3;
            condition3.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printC() throws InterruptedException {
        lock.lock();
        try {
            while (data != 3) {
                //等待
                condition3.await();
            }
            System.out.println(Thread.currentThread().getName() + "printC---data = " + data);
            data = 1;
            condition1.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

集合类不安全

list不安全

变量的线程安全问题

public static void listTest1(){
    //ConcurrentModificationException :并发修改异常
    //并发下arrayList 不安全
    List<String> list1 = new ArrayList();
    //⭐️ArrayList可以转为线程安全的,下面的list2 再操作便不会报ConcurrentModificationException
    List<Object> list2 = Collections.synchronizedList(new ArrayList());


    //⭐️Vector在多线程中是安全的。Vector中add方法有synchronized修饰。
    List<String> list3 = new Vector<>();

    //CopyOnWriteArrayList 也是线程安全的集合:(写入时复制 COW 计算机程序设计领域的优化策略)
    //写入的时候避免覆盖,造成数据问题。
    //CopyOnWriteArrayList 比 Vector 厉害的点:
    //Vector 被 synchronized修饰  CopyOnWriteArrayList用的是Lock锁   CopyOnWriteArrayList 效率高于 Vector

    List<String> list = new CopyOnWriteArrayList<>();


    for (int i = 0; i < 10; i++) {
        new Thread(() -> {
            list.add(UUID.randomUUID().toString().substring(0, 5));
            System.out.println(Thread.currentThread().getName() + "--->" + list);
        }, String.valueOf(i + 1)).start();
    }
}

CopyOnWriteArrayList 的add()源码

public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}

Set 不安全 (同ArrayList)

public static void setTest1(){
    //ConcurrentModificationException :并发修改异常
    //并发下 HashSet 不安全
    Set<String> set1 = new HashSet<>();
    
    //⭐HashSet 可以转为线程安全的,下面的set2 再操作便不会报ConcurrentModificationException
    Set<String> set2 = Collections.synchronizedSet(new HashSet());

    //CopyOnWriteArraySet 也是线程安全的集合:(写入时复制 COW 计算机程序设计领域的优化策略)
    Set<String> set = new CopyOnWriteArraySet<>();


    for (int i = 0; i < 10; i++) {
        new Thread(() -> {
            set.add(UUID.randomUUID().toString().substring(0, 5));
            System.out.println(Thread.currentThread().getName() + "--->" + set);
        }, String.valueOf(i + 1)).start();
    }
}

HashSet是什么?

/**
 * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
 * default initial capacity (16) and load factor (0.75).
 */
public HashSet() {
    map = new HashMap<>();
}
//add   PRESENT 就是一个不变的虚拟值。
 public boolean add(E e) {
        return map.put(e, PRESENT)==null;
 }

HashSet 底层就是HashMap.利用了Map的 key不重复。

Map 不安全

public static void mapTest1(){
    //ConcurrentModificationException :并发修改异常
    //并发下 HashMap 不安全
    Map<String,String> map1 = new HashMap<>();
    
    //⭐HashMap 可以转为线程安全的,下面的 map2 再操作便不会报ConcurrentModificationException
    Map<String,String> map2 = Collections.synchronizedMap(new HashMap());

    //ConcurrentHashMap 也是线程安全的集合:(写入时复制 COW 计算机程序设计领域的优化策略)
    Map<String,String> map = new ConcurrentHashMap<>();


    for (int i = 0; i < 10; i++) {
        new Thread(() -> {
            map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0, 5));
            System.out.println(Thread.currentThread().getName() + "--->" + map);
        }, String.valueOf(i + 1)).start();
    }
}

Callable

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}
public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //如何启动callable
        // new Thread(new Runnable()).start();
        // new Thread(new FutureTask()).start();
        // new Thread(new FutureTask(Callable callable)).start();
        //Thread() 只能传 Runnable 参数,FutureTask是Runbable的实现类,FutureTask可以接收Callable类型的参数。
        MyThread myThread = new MyThread();
        //适配类
        FutureTask futureTask = new FutureTask(myThread);
        new Thread(futureTask,"A").start();
        new Thread(futureTask,"B").start();//结果会被缓存。
        //get可能会产生阻塞,可使用异步通信解决
        Object o = futureTask.get();
        System.out.println(o);
    }
}
class MyThread implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("call");
        return 1024;
    }
}CountDownLatch

常用的辅助类

CountDownLatch 递减计数器

public static void main(String[] args) throws InterruptedException {
    //计数器初始化为6次。线程调用的次数  
    CountDownLatch count = new CountDownLatch(6);
    for (int i = 0; i < 6; i++) {
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"---Go");
            count.countDown();
        }).start();
    }
    count.await();//等待计数器归零,然后向下执行
    System.out.println("Over");
}

CyclicBarrier 循环障碍(递增计数)

//集齐七龙珠,召唤神龙
public static void main(String[] args) {
    CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
        System.out.println("召唤神龙");
    });
    for (int i = 0; i < 7; i++) {
        int finalI = i;
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"收集了"+(finalI+1));
            try {
                cyclicBarrier.await();//等待计数器达到设置的次数
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

Semaphore 信号量

public static void main(String[] args) {
    //信号量:(类比有三个车位,6个车)  可用于资源限流
    Semaphore semaphore = new Semaphore(3);
    //
    for (int i = 0; i < 6; i++) {
        new Thread(()->{
            try {
                semaphore.acquire();//获取信号量
                System.out.println(Thread.currentThread().getName()+"进入车位");
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                semaphore.release();//释放信号量
                System.out.println(Thread.currentThread().getName()+"离开车位");

            }
        },i+"").start();
    }
}

读写锁

public class ReadWriteLockDemo {

    /**
     * 独占锁:== 写锁
     * 共享锁:== 读锁
     *
     * ReadWriteLock 读写锁
     * 读-读:可以共存
     * 读-写:不能共存
     * 写-写:不能共存
     */
    public static void main(String[] args) {
        //MyCache myCache = new MyCache();
        MyCacheLock myCache = new MyCacheLock();
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            new Thread(() -> {
                myCache.write(finalI + "", Thread.currentThread().getName());
            }).start();
        }

        for (int i = 0; i < 10; i++) {
            int finalI = i;
            new Thread(() -> {
                myCache.read(finalI + "");
            }).start();
        }

    }

}

class MyCacheLock {

    /**
     * ReentrantReadWriteLock 读写锁有更高颗粒度的控制
     */
    ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    /**
     * ReentrantLock 普通锁的颗粒度不够,多线程读取数据有问题
     */
    //ReentrantLock lock = new ReentrantLock();

    private volatile Map<String, String> map = new HashMap<>();

    //读的时候所有线程都可以读取
    public String read(String key) {
        ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "读数据,key = " + key);
            return map.get(key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readLock.unlock();
            return null;
        }
    }

    //存的时候只能有一个线程操作
    public void write(String key, String value) {
        ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
        writeLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "写数据开始");
            map.put(key, value);
            System.out.println(Thread.currentThread().getName() + "写数据结束");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            writeLock.unlock();
        }
    }
}

class MyCache {
    private volatile Map<String, String> map = new HashMap<>();

    public String read(String key) {
        System.out.println(Thread.currentThread().getName() + "读数据,key = " + key);
        return map.get(key);
    }

    public void write(String key, String value) {
        System.out.println(Thread.currentThread().getName() + "写数据开始");
        map.put(key, value);
        System.out.println(Thread.currentThread().getName() + "写数据结束");
    }

}

阻塞队列

操作 抛异常 有返回值,不抛异常 阻塞等待 超时等待
添加 add() offer() put() offer(,,)
移除 remove() poll() take() poll(,)
检测队首元素 Element() peek()
//add remove element 会抛异常
public static void test1(){
    ArrayBlockingQueue queue = new ArrayBlockingQueue<>(3);
    queue.add("a");
    queue.add("b");
    queue.add("c");
    //检索队首元素  如果此队列为空,它将抛出异常
    //System.out.println(queue.element());
    //对满,抛异常  IllegalStateException: Queue full
    //queue.add("d");
    System.out.println(queue.remove());
    System.out.println(queue.remove());
    System.out.println(queue.remove());
    //对空,抛异常
    //queue.remove();
}

//offer poll peek 不会抛异常
public static void test2(){
    ArrayBlockingQueue queue = new ArrayBlockingQueue<>(3);
    queue.offer("a");
    queue.offer("b");
    queue.offer("c");
    //检索队首元素  如果此队列为空,返回null
    System.out.println(queue.peek());
    //对满,不抛异常  IllegalStateException: Queue full
    queue.offer("d");
    System.out.println(queue.poll());
    System.out.println(queue.poll());
    System.out.println(queue.poll());
    //对空,抛异常
    //queue.poll();
}
// put take  阻塞等待
public static void test3() throws InterruptedException {
    ArrayBlockingQueue queue = new ArrayBlockingQueue<>(3);
    queue.put("a");
    queue.put("b");
    queue.put("c");
    //对满,阻塞等待
    //queue.put("d");
    System.out.println(queue.take());
    System.out.println(queue.take());
    System.out.println(queue.take());
    //对空,抛异常
    //queue.take();
}

//offer(,,) poll(,) 超时等待
public static void test4() throws InterruptedException {
    ArrayBlockingQueue queue = new ArrayBlockingQueue<>(3);
    queue.offer("a");
    queue.offer("b");
    queue.offer("c");
    //对满,超时等待
    queue.offer("d",2,TimeUnit.SECONDS);
    System.out.println(queue.poll());
    System.out.println(queue.poll());
    System.out.println(queue.poll());
    //对空,超时等待
    queue.poll(2,TimeUnit.SECONDS);
}

SynchronousQueue 同步队列

​ 没有容量,必须等待元素取出来之后,才能放进去新的元素

/**
 * 和其他的BlockingQueue 不一样, SynchronousQueue 不存储元素
 *  put了一个元素,必须从里面先take取出来,否则不能在put进去值!
 * */
public static void main(String[] args) {
    SynchronousQueue<String> synchronousQueue = new SynchronousQueue();
    new Thread(() -> {
        try {
            System.out.println(Thread.currentThread().getName() + " put 1");
            synchronousQueue.put("1");
            System.out.println(Thread.currentThread().getName() + " put 2");
            synchronousQueue.put("2");
            System.out.println(Thread.currentThread().getName() + " put 3");
            synchronousQueue.put("3");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }, "t1").start();
    new Thread(() -> {
        try {
            TimeUnit.SECONDS.sleep(3);
            System.out.println(Thread.currentThread().getName()+" take "+synchronousQueue.take());
            TimeUnit.SECONDS.sleep(3);
            System.out.println(Thread.currentThread().getName()+" take "+synchronousQueue.take());
            TimeUnit.SECONDS.sleep(3);
            System.out.println(Thread.currentThread().getName()+" take "+synchronousQueue.take());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }, "t2").start();
}
/**
t1 put 1
t1 put 2
t2 take 1
t2 take 2
t1 put 3
t2 take 3
*/

线程池

线程池程序运行-》占用系统资源。为了优化资源的使用-》池化技术。

线程池、连接池、内存池、对象池///..... 创建、销毁。十分浪费资源
池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。

线程池的好处

降低资源的消耗、提高响应的速度、方便管理。(线程复用、可以控制最大并发数、线程管理)

线程的三大方法

![image-20220307144102355](/Users/weiyi/Library/Application Support/typora-user-images/image-20220307144102355.png)

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
 }

 public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
 }

七大参数

public ThreadPoolExecutor(int corePoolSize, //核心线程数量
                          int maximumPoolSize, //最大线程数
                          long keepAliveTime, //超时了多久没人调用就释放
                          TimeUnit unit, //超时时间单位
                          BlockingQueue<Runnable> workQueue,//阻塞队列
                          ThreadFactory threadFactory, //线程工厂 创建线程的一般不用动
                          RejectedExecutionHandler handler //拒绝策略
) {
    if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

手动创建线程池

public static void main(String[] args) {
  			// 最大线程到底该如何定义
        // 1、CPU 密集型,几核,就是几,可以保持CPu的效率最高!
        // 2、IO  密集型   > 判断你程序中十分耗IO的线程,
        //   假设 程序有15个大型任务 ,io十分占用资源,那就至少留15个max线程(一般来两倍)
        // 获取CPU的核数
        System.out.println(Runtime.getRuntime().availableProcessors());
    //手动创建线程成
    ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
            2,
            5,
            3,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(3),
            Executors.defaultThreadFactory(),
            //抛出RejectedExecutionException的被拒绝任务的处理程序。
            //new ThreadPoolExecutor.AbortPolicy()

            //被拒绝任务的处理程序,直接在execute方法的调用线程中运行被拒绝的任务(main线程执行),除非执行程序已关闭,在这种情况下,任务将被丢弃。
            //new ThreadPoolExecutor.CallerRunsPolicy()

            //拒绝任务的处理程序,丢弃最旧的未处理请求,然后重试execute ,除非执行程序被关闭,在这种情况下任务被丢弃。
            //new ThreadPoolExecutor.DiscardOldestPolicy()

            //被拒绝任务的处理程序,它默默地丢弃被拒绝的任务。
            new ThreadPoolExecutor.DiscardOldestPolicy()
    );

    try {
        for (int i = 0; i < 5; i++) {

            int finalI = i;
            poolExecutor.execute(() -> {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                printInfo(poolExecutor, finalI + "");
            });
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        poolExecutor.shutdown();
    }
}

public static void printInfo(ThreadPoolExecutor executor, String name) {
    BlockingQueue<Runnable> queue = executor.getQueue();
    System.out.println(Thread.currentThread().getName() + "--->"+name+"<----" +
            "核心数: " + executor.getCorePoolSize() +
            " 活动线程数: " + executor.getActiveCount() +
            " 最大线程数: " + executor.getMaximumPoolSize() +
            " 任务完成数: " + executor.getCompletedTaskCount() +
            " 队列大小: " + (queue.size() + queue.remainingCapacity()) +
            " 当前排队线程数: " + queue.size() +
            " 队列剩余大小: " + queue.remainingCapacity()
    );
}

函数式接口

函数式接口:只包含一个抽象方法的接口,称为函数式接口

Eg:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

Function:函数

public static void main(String[] args) {
        Function function = new Function<String, Object>() {
            @Override
            public Object apply(String o) {
                return o;
            }
        };
        //lambda简化
        Function function1  = (str)->{return str;};
        Function function2  = (str)-> str;

        System.out.println(function.apply("str"));
 }

Predicate:断言

public static void main(String[] args) {
    Predicate predicate = new Predicate<String>() {
        @Override
        public boolean test(String str) {
            return str.isEmpty();
        }
    };
    //lambda简化
    Predicate<String> predicate1 = str-> str.isEmpty();

    System.out.println(predicate.test("s"));
    System.out.println(predicate1.test(""));
}

Consumer:消费型接口

/**
 * 消费型接口
 */
public static void main(String[] args) {
    Consumer<Object> consumer = new Consumer<Object>() {
        @Override
        public void accept(Object o) {
            System.out.println(o);
        }
    };
    Consumer<Object> consumer1 = str-> System.out.println(str);
    consumer.accept("ssssss");
}

Supplier:供给型接口

/**
 * 供给型接口
 */
public static void main(String[] args) {
    Supplier<Object> supplier = new Supplier<Object>() {
        @Override
        public Object get() {
            return "hello";
        }
    };
    Supplier<Object> supplier1 = ()-> "hello";
    System.out.println(supplier.get());
}

ForkJoin

ForkJoin 在 JDK 1.7 , 并行执行任务!提高效率。大数据量!工作窃取。

假如我们需要做一个比较大的任务,我们可以把这个任务分割为若干互不依赖的子任务,为了减少线程间的竞争,于是把这些子任务分别放到不同的队列里,并为每个队列创建一个单独的线程来执行队列里的任务,线程和队列一一对应,比如 A 线程负责处理 A 队列里的任务。但是有的线程会先把自己队列里的任务干完,而其他线程对应的队列里还有任务等待处理。干完活的线程与其等着,不如去帮其他线程干活,于是它就去其他线程的队列里窃取一个任务来执行。而在这时它们会访问同一个队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常会使用双端队列,被窃取任务线程永远从双端队列的头部拿任务执行,而窃取任务的线程永远从双端队列的尾部拿任务执行。

class ForkJoinTask extends RecursiveTask<Long> {
    private Long threshold = 100L;
    private Long start;
    private Long end;

    public ForkJoinTask(Long start, Long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        long sum = 0;
        if ((end - start) < threshold) {
            for (long i = start; i <= end; i++) {
                sum += i;
            }

        } else {
            long mid = (start + end) / 2;
            ForkJoinTask forkJoinTask1 = new ForkJoinTask(start, mid);
            ForkJoinTask forkJoinTask2 = new ForkJoinTask(mid + 1, end);
            forkJoinTask1.fork();
            forkJoinTask2.fork();
            Long join1 = forkJoinTask1.join();
            Long join2 = forkJoinTask2.join();
            sum = join1 + join2;
        }
        return sum;
    }
}
public static Long test() throws ExecutionException, InterruptedException {
        ForkJoinPool joinPool = new ForkJoinPool();
        ForkJoinTask forkJoinTask = new ForkJoinTask(1L, 100_000_0000L);
        java.util.concurrent.ForkJoinTask<Long> submit = joinPool.submit(forkJoinTask);
        Long aLong = submit.get();
        System.out.println(aLong);
        return aLong;
    }
posted @   iyandongsheng  阅读(92)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示