Java并发编程(2)

1.CountDownLatch

        允许一个或多个线程等待其他线程完成操作。

        CountDownLatch的单参构造传入count,因此只能限制count个线程(即countDown()调用count次,不能多也不能少)。让主线程和t3线程等待t1和t2线程先完成操作。

//需要2个线程先完成操作
    static CountDownLatch countDownLatch = new CountDownLatch(2);
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("线程t1操作");
            //t1线程完成操作后,count减1
            countDownLatch.countDown();
        }, "t1");
        Thread t2 = new Thread(() -> {
            System.out.println("线程t2操作");
            //t2线程完成操作后,count减1
            countDownLatch.countDown();
        }, "t2");
        Thread t3 = new Thread(() -> {
            try {
                //当count==0时,解除阻塞(t1,t2线程先完成操作)
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程t3操作");
        }, "t3");

        //三线程并发执行
        t1.start();
        t2.start();
        t3.start();
        
        //让主线程等待其他线程完成操作 当count==0时,解除阻塞(t1,t2线程先完成操作)
        countDownLatch.await();
        System.out.println("t1,t2已完成操作");

2.CyclicBarrier

        CyclicBarrier 让一组线程到达一个屏障时阻塞,直到最后一个线程到达屏障后,被阻塞的线程组并发执行。利用await()方法阻塞线程。

//定义2个线程到达屏障前,执行任务
    static CyclicBarrier cyclicBarrier = new CyclicBarrier(3,()->{
        System.out.println("该任务先于线程t1,t2执行");
    });
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                //线程1到达屏障
                cyclicBarrier.await();
                System.out.println("线程1进行操作");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "t1");

        Thread t2 = new Thread(() -> {
            try {
                //线程2到达屏障
                cyclicBarrier.await();
                System.out.println("线程2进行操作");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "t2");

        Thread t3 = new Thread(() -> {
            try {
                //线程3到达屏障
                cyclicBarrier.await();
                System.out.println("线程3进行操作");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "t3");

        Thread t4 = new Thread(() -> {
            try {
                //线程4到达屏障
                cyclicBarrier.await();
                System.out.println("线程4进行操作");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "t4");

        Thread t5 = new Thread(() -> {
            try {
                //线程5到达屏障
                cyclicBarrier.await();
                System.out.println("线程5进行操作");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "t5");

        t1.start();
        t2.start();

        //CyclicBarrier重用性。线程3,4可以继续使用该对象
        Thread.sleep(3000);
        t3.start();
        t4.start();

        //reset()方法会使屏障前等待的线程抛出异常
        t5.start();
        Thread.sleep(3000);
        cyclicBarrier.reset();
    }

  3.Semaphore

        Semaphore用来控制同时访问资源的线程数量。控制并发数。

    //控制并发数3
    static Semaphore semaphore = new Semaphore(3);
    public static void main(String[] args){
        //30个线程并发
        ArrayList<Thread> threads = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            final int num = i;
            threads.add(new Thread(()->{
                try {
                    //获取许可
                    semaphore.acquire();
                    Thread.sleep(3000);
                    System.out.println("线程t"+num+"开始操作");
                    //释放许可
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }));
        }
        threads.stream().forEach(x->x.start());

3.Exchanger

        Exchanger 用于两个线程之间交换数据。 V exchange(V x)方法会阻塞线程,直到另一个线程也执行了exchange(V x)方法。

4.线程池

//package org.apache.tomcat.util.threads;
ThreadPoolExecutor(int corePoolSize,//核心线程数 ,tomcat默认10个
                     int maximumPoolSize,//最大线程数,tomcat默认200
                     long keepAliveTime,//最大空闲时间,闲置线程的最大存活时间 tomcat默认60s
                     TimeUnit unit,//时间单位 纳秒
                     BlockingQueue<Runnable> workQueue,//任务队列
            ThreadFactory threadFactory, //线程工厂 tomcat默认线程前缀http-nio-8080-exec-
            //饱和处理机制 tomcat默认 RejectHandler拒绝,报异常RejectedExecutionException
            RejectedExecutionHandler handler);
allowCoreThreadTimeOut 是否允许销毁核心线程,tomcat 默认false
workers 工作线程HashSet<Worker>,存放的是线程。最大值为maximumPoolSize
workersQueue 任务链表队列(7992) + maximumPoolSize核心线程数(200) = maxConnections最大连接(8192)  //tomcat9.0.0以上默认值,大于maximumPoolSize值时,创建workersQueue
acceptCount(100)  accept队列到达acceptCount之后,进来的请求会执行RejectHandler(服务器同时接受请求acceptCount+maxConnections) 。 
//向线程池提交一个请求时,线程池的execute()主要流程
1.判断线程池里的核心线程数是否都在执行任务,如果不是,则新建线程来执行任务。是,则进入下一环节。
2.判断工作队列是否已满,如果不是,则新提交的任务储存在工作队列中。是,则进入下一环节。
3.判断线程池是否达到最大线程数,如果不是,则创建线程来执行任务。是,则交给饱和策略。          
                  
//饱和策略接口,实现该接口处理任务。  Runnable接口的实现类NioEndpoint.SocketProcessor
public interface RejectedExecutionHandler{ 
void rejectedExecution(Runnable r,ThreadPoolExecutor executor);
}

AbortPolicy 丢弃任务并抛出RejectedExecutionException异常。
DiscardPolicy:丢弃任务,但是不抛出异常。
DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务

 5.Executor

//创建固定数量的线程池 LinkedBlockingQueue无界所以不会拒绝任务 coreThread==maximumPoolSize
Executors.newFixedThreadPool(2);

//创建有一个线程work的线程池 LinkedBlockingQueue所以不会拒绝任务 coreThread==maximumPoolSize=1
Executors.newSingleThreadExecutor();

//创建一个根据需要创建线程60s的线程池,SynchronousQueue coreThread=0,maximumPoolSize=Integer.MAX_VALUE
//特点,线程无限创建
Executors.newCachedThreadPool();

//创建核心线程数为2,最大线程数Integer.MAX_VALUE,阻塞队列DelayedWorkQueue
new ScheduledThreadPoolExecutor(2);
//scheduleFixedDelay() //超过定时周期period,则当前任务结束后会立即执行
//scheduleWithFixedDelay() //延时是相对当前任务结束为起点计算开始时间

 6.定时器Timer

//schedule(TimerTask task, long delay)//在延时固定时间执行任务
//schedule(TimerTask task, long delay, long period) //在delay后执行任务,之后每个period执行任务
//scheduleAtFixedRate(TimerTask task, long delay, long period) //与上一个基本相同,不同的是它是相对于初始执行计划的调度。

         

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值