Java多线程并发工具类

CountDownLauch

作用:是一组线程等待其他的线程完成工作以后在执行,加强版join

await用来等待,countDown负责计数器的减一

countDownLauch设定的次数必须减少到0,await的方法才会被唤醒向下继续执行,否则当一直处于阻塞状态

public class CountDownLatchDemo {
    static CountDownLatch countDownLatch = new CountDownLatch(5);

    private static class MyWork extends Thread {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " do work");
            countDownLatch.countDown();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("main wait other work done");
        Thread.sleep(1000);
        for (int i = 0; i < 5; i++) {
            new MyWork().start();
        }
        countDownLatch.await();
        System.out.println("main do work");
    }
}

运行结果:

main wait other work done
Thread-0 do work
Thread-3 do work
Thread-1 do work
Thread-4 do work
Thread-2 do work
main do work

CyclicBarrier

 CyclicBarrier(int parties) 让一组线程达到某个屏障,被阻塞,一直到组内最后一个线程达到屏障时,屏障开放,所有被阻塞的线程会继续运行
CyclicBarrier(int parties, Runnable barrierAction),屏障开放,barrierAction定义的任务会执行

示例1:CyclicBarrier(int parties)

public class CyclicBarrierDemo {
    static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);

    static class MyWork extends Thread {
        @Override
        public void run() {
            Random r = new Random();
            try {
                if (r.nextBoolean()) {
                    System.out.println("Thread " + Thread.currentThread().getId() + " is sleeping");
                    Thread.sleep(2000);
                }
                System.out.println("Thread " + Thread.currentThread().getId() + " is await");
                cyclicBarrier.await();//等待其他线程完毕
                System.out.println("Thread " + Thread.currentThread().getId() + " is working");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            new MyWork().start();
        }
    }
}

结果:

Thread 14 is await
Thread 13 is sleeping
Thread 12 is sleeping
Thread 11 is sleeping
Thread 15 is sleeping
Thread 13 is await
Thread 12 is await
Thread 11 is await
Thread 15 is await
Thread 15 is working
Thread 14 is working
Thread 12 is working
Thread 13 is working
Thread 11 is working

示例2:CyclicBarrier(int parties, Runnable barrierAction)

    static CyclicBarrier cyclicBarrier = new CyclicBarrier(5,new OtherWork());

    static class OtherWork implements Runnable{
        @Override
        public void run() {
            System.out.println("Other work is doing");
        }
    }

结果:

Thread 15 is await
Thread 11 is sleeping
Thread 14 is sleeping
Thread 12 is sleeping
Thread 13 is await
Thread 14 is await
Thread 11 is await
Thread 12 is await
Other work is doing
Thread 15 is working
Thread 13 is working
Thread 14 is working
Thread 11 is working
Thread 12 is working

CountDownLauch & CyclicBarrier 的区别

1、countdownlatch放行由第三者控制,CyclicBarrier放行由一组线程本身控制
2、countdownlatch放行条件》=线程数,CyclicBarrier放行条件=线程数

Semaphore

控制同一时刻方法资源的数量

Semaphore(int permits) 表示同时获得资源数量
acquire() 从信号量容器中获取可用的信号量,信号量数量-1,如果没有可用信号量则阻塞
release()归还信号量到信号量容器中,信号量数量+1

示例:模拟获取数据库连接,规定同时只有10个可用数据库连接

public class SemaphoreDemo {
    private final static int POOL_SIZE = 10;
    static LinkedList<Connection> pool = new LinkedList<Connection>();
    private Semaphore useable,unUseable;//useable表示可用的信号量,unUseable表示不可用

    public SemaphoreDemo(){
        useable = new Semaphore(10);
        unUseable = new Semaphore(0);
    }

    static {
        for (int i = 0; i < POOL_SIZE; i++) {
            pool.add(MyConnection.getInstance());
        }
    }

    public void releaseConnection(Connection connection) throws InterruptedException {
        if(connection != null){
            unUseable.acquire();
            synchronized (pool){
                pool.addLast(connection);
            }
            useable.release();
            System.out.println("当前可用连接数为:"+useable.availablePermits()+",等待连接数:"+useable.getQueueLength());
        }
    }

    public Connection getConnection() throws InterruptedException {
        useable.acquire();
        Connection connection = null;
        synchronized (pool){
            connection = pool.removeFirst();
        }
        unUseable.release();
        return connection;
    }
}

public class SemaphoreTest {
    static SemaphoreDemo demo = new SemaphoreDemo();

    static class ConnectionThread extends Thread {
        @Override
        public void run() {
            long start = System.currentTimeMillis();
            try {
                Connection connection = demo.getConnection();
                System.out.println("Thread_" + Thread.currentThread().getId()
                        + "_获取数据库连接共耗时【" + (System.currentTimeMillis() - start) + "】ms.");
                Thread.sleep(100);//模拟业务操作,线程持有连接查询数据
                System.out.println("Thread_" + Thread.currentThread().getId()
                        + "查询数据完成,归还连接!");
                demo.releaseConnection(connection);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            new ConnectionThread().start();
        }
    }
}

 运行结果:

hread_11_获取数据库连接共耗时【0】ms.
Thread_14_获取数据库连接共耗时【0】ms.
Thread_13_获取数据库连接共耗时【0】ms.
Thread_12_获取数据库连接共耗时【0】ms.
Thread_16_获取数据库连接共耗时【0】ms.
Thread_17_获取数据库连接共耗时【0】ms.
Thread_18_获取数据库连接共耗时【0】ms.
Thread_20_获取数据库连接共耗时【0】ms.
Thread_15_获取数据库连接共耗时【0】ms.
Thread_21_获取数据库连接共耗时【0】ms.
Thread_11查询数据完成,归还连接!
Thread_19_获取数据库连接共耗时【97】ms.
当前可用连接数为:0,等待连接数:9
Thread_14查询数据完成,归还连接!
Thread_22_获取数据库连接共耗时【98】ms.
当前可用连接数为:0,等待连接数:8
Thread_18查询数据完成,归还连接!
Thread_23_获取数据库连接共耗时【98】ms.
当前可用连接数为:0,等待连接数:7
Thread_12查询数据完成,归还连接!
当前可用连接数为:1,等待连接数:7
Thread_15查询数据完成,归还连接!
当前可用连接数为:2,等待连接数:7
Thread_16查询数据完成,归还连接!
当前可用连接数为:2,等待连接数:6
Thread_24_获取数据库连接共耗时【99】ms.
Thread_20查询数据完成,归还连接!
当前可用连接数为:2,等待连接数:5
Thread_25_获取数据库连接共耗时【100】ms.
Thread_13查询数据完成,归还连接!
当前可用连接数为:3,等待连接数:5
Thread_17查询数据完成,归还连接!
当前可用连接数为:4,等待连接数:5
Thread_21查询数据完成,归还连接!
当前可用连接数为:5,等待连接数:5
Thread_27_获取数据库连接共耗时【100】ms.
Thread_29_获取数据库连接共耗时【100】ms.
Thread_26_获取数据库连接共耗时【100】ms.
Thread_28_获取数据库连接共耗时【100】ms.
Thread_30_获取数据库连接共耗时【100】ms.
Thread_19查询数据完成,归还连接!
当前可用连接数为:1,等待连接数:0
Thread_22查询数据完成,归还连接!
当前可用连接数为:2,等待连接数:0
Thread_23查询数据完成,归还连接!
当前可用连接数为:3,等待连接数:0
Thread_24查询数据完成,归还连接!
当前可用连接数为:4,等待连接数:0
Thread_25查询数据完成,归还连接!
当前可用连接数为:5,等待连接数:0
Thread_26查询数据完成,归还连接!
当前可用连接数为:6,等待连接数:0
Thread_30查询数据完成,归还连接!
当前可用连接数为:7,等待连接数:0
Thread_27查询数据完成,归还连接!
当前可用连接数为:8,等待连接数:0
Thread_28查询数据完成,归还连接!
当前可用连接数为:9,等待连接数:0
Thread_29查询数据完成,归还连接!
当前可用连接数为:10,等待连接数:0

Exchange

只能两个线程间的数据交换

示例:

public class ExchangeDemo {
    static Exchanger<Set<String>> exchanger = new Exchanger<>();

    static class MyThreadA extends Thread {
        @Override
        public void run() {
            Set<String> setA = new HashSet<>();
            setA.add("AAA");
            setA.add("BBB");
            setA.add("CCC");
            try {
                System.out.println("MyThreadA is waiting");
                setA = exchanger.exchange(setA);
                System.out.println("MyThreadA:" + setA);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class MyThreadB extends Thread {
        @Override
        public void run() {
            Set<String> setB = new HashSet<>();
            setB.add("DDD");
            setB.add("EEE");
            setB.add("FFF");
            try {
                Thread.sleep(1000);
                System.out.println("MyThreadB is waiting");
                setB = exchanger.exchange(setB);
                System.out.println("MyThreadB:" + setB);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new MyThreadA().start();
        new MyThreadB().start();
    }
}

运行结果:

MyThreadA is waiting
MyThreadB is waiting
MyThreadB:[AAA, CCC, BBB]
MyThreadA:[EEE, DDD, FFF]

Callable, Future & FutureTask

三者之间的关系:

 使用方式:new Thread(new FutureTask(new Callable()));

isDone,结束,正常还是异常结束,或者自己取消,返回true;

isCancelled 任务完成前被取消,返回true;

cancel(boolean):

  1. 任务还没开始,返回false
  2. 任务已经启动,cancel(true),中断正在运行的任务,中断成功,返回true,cancel(false),不会去中断已经运行的任务
  3. 任务已经结束,返回false

示例:

public class CallableDemo {
    static class MyCallable implements Callable<Integer> {
        int count;
        @Override
        public Integer call() throws Exception {
            System.out.println("Call ready to sum");
            Thread.sleep(2000);
            for (int i = 0; i < 50; i++) {
                count += i;
            }
            return count;
        }
    }

    public static void main(String[] args) throws Exception {
        Callable<Integer> callable = new MyCallable();
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        new Thread(futureTask).start();
        Random random = new Random();
        if(random.nextBoolean()){
            System.out.println("计算的结果为:"+futureTask.get());
        }else{
            futureTask.cancel(true);
            System.out.println("task is cancle");
        }
    }
}

运行结果:

Call ready to sum
计算的结果为:1225

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值