六、JUC强大的辅助类

六、JUC强大的辅助类

6.1 多线程中创建线程的方式

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * 多线程中创建线程的方式
 * 1、   继承Thread类
 * 2、   实现Runnable接口
 * 3、   实现Callable接口
 * 4、   实现Callable接口通过FutureTask包装器来创建Thread线程
 */
public class CallableDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask futureTask = new FutureTask(new MyThread());

        System.out.println(Thread.currentThread().getName()+"计算完成");

        //***Callable***  只调用了一次
        new Thread(futureTask, "A").start();
        new Thread(futureTask, "B").start();

        System.out.println(futureTask.get());
    }
}

在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给Future对象在后台完成,当主线程将来需要时,就可以通过Future对象获得后台作业的计算结果或者执行状态。一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞get 方法。一旦计算完成,就不能再重新开始或取消计算。get方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常。 只计算一次get方法放到最后

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
 * Callable接口与Runnable接口的异同
 *  1、      是否有返回值
 *  2、      是否抛异常
 *  3、      落地方法不一样,一个是run,一个是call
 */
 class MyThread implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        try { TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}
        System.out.println("***Callable***");
        return 1024;
    }
}

 class MyThread2 implements Runnable{
    @Override
    public void run() {

    }
}

6.2 CountDownLatch

import java.util.concurrent.CountDownLatch;

/**
 * CyclicBarrier的字面意思是可循环(Cyclic)使用的屏障(Barrier)。
 * 它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞
 * 直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。
 * 线程进入屏障通过CyclicBarrier的await()方法。
 */
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t离开教室");
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "\t班长关门");
    }

    private static void CloseDoor() {
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t离开教室");
            }, String.valueOf(i)).start();
        }
        System.out.println(Thread.currentThread().getName() + "\t班长关门");
    }
}

在这里插入图片描述

6.3 Semaphore

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 * 在信号量上我们定义两种操作:
 * acquire(获取): 当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),要么一直等下去,直到有线程释放信号量,或超时。
 * release(释放):实际上会将信号量的值加1,然后唤醒等待的线程。
 * 信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制。
 */
public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(1);//模拟资源类,有三个空车位
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "\t抢占了车位");
                    //暂停一会线程
                    try { TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
                    System.out.println(Thread.currentThread().getName() + "\t离开了车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();
                }
            }, String.valueOf(i)).start();
        }
    }
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值