多线程常用类

1. Callable

多线程常用类

使用方法:

public class CallableDemo {
    public static void main(String[] args) {
        CallableTest callableTest = new CallableTest();
        FutureTask<Integer> futureTask  = new FutureTask(callableTest);
        new Thread(futureTask,"t1").start();
        try {
            System.out.println(futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}


class CallableTest implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        Integer num = 0;
        for (int i = 0; i < 10; i++) {
            num++;
        }
        return num;
    }
}

优点:

  • 可以获取通过get方法获取线程的返回值,注意get方法阻塞线程。
  • 支持异常捕获
  • 支持泛型

2. CountDownLatch

 

CountDownLatch(倒计时计算器)使用说明

方法说明

public void countDown()

  递减锁存器的计数,如果计数到达零,则释放所有等待的线程。如果当前计数大于零,则将计数减少.

public boolean await(long timeout,TimeUnit unit) throws InterruptedException

  使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。如果当前计数为零,则此方法立刻返回true值。

  如果当前计数大于零,则出于线程调度目的,将禁用当前线程,且在发生以下三种情况之一前,该线程将一直出于休眠状态:

  由于调用countDown()方法,计数到达零;或者其他某个线程中断当前线程;或者已超出指定的等待时间。

  • 如果计数到达零,则该方法返回true值。
  • 如果当前线程,在进入此方法时已经设置了该线程的中断状态;或者在等待时被中断,则抛出InterruptedException,并且清除当前线程的已中断状态。
  • 如果超出了指定的等待时间,则返回值为false。如果该时间小于等于零,则该方法根本不会等待。

参数:

  timeout-要等待的最长时间

  unit-timeout 参数的时间单位

返回:

  如果计数到达零,则返回true;如果在计数到达零之前超过了等待时间,则返回false

抛出:

  InterruptedException-如果当前线程在等待时被中断

例子:线程a需要等待线程b和c完成在执行

public class CountDownLatchDemo {
    public static void main(String[] args) {
        CDLDPrint cdldPrint = new CDLDPrint();
       final CountDownLatch latch = new CountDownLatch(2);  //需要等待b,c线程完成,所以为2
        new Thread(()->{
            try {
                latch.await();    //等待bc线程执行完成
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            cdldPrint.printA();
        },"线程A").start();


        new Thread(()->{
            cdldPrint.printB();
            latch.countDown();  //计数器减一
        },"线程B").start();
        new Thread(()->{
            cdldPrint.printC();
            latch.countDown();   //计数器减一
        },"线程C").start();
    }
}

class CDLDPrint{

    public void printA(){
        System.out.println(Thread.currentThread().getName()+"aaaaaaaaaaaaaaaaa");
    }
    public void printB(){
        System.out.println(Thread.currentThread().getName()+"bbbbbbbbbbbbbbbb");
    }
    public void printC(){
        System.out.println(Thread.currentThread().getName()+"ccccccccccccccccc");
    }

}

多线程常用类

3. CyclicBarrier

就像生活中我们会约朋友们到某个餐厅一起吃饭,有些朋友可能会早到,有些朋友可能会晚到,但是这个餐厅规定必须等到所有人到齐之后才会让我们进去。这里的朋友们就是各个线程,餐厅就是 CyclicBarrier。类似于累加器,线程运行达到多少时,开始执行。

public int await()
          throws InterruptedException,
                 BrokenBarrierException

等待所有parties已经在这个障碍上调用了await

如果当前线程不是最后一个线程,那么它被禁用以进行线程调度,并且处于休眠状态,直到发生下列事情之一:

  • 最后一个线程到达; 要么
  • 一些其他线程当前线程为interrupts ; 要么
  • 一些其他线程interrupts其他等待线程之一; 要么
  • 一些其他线程在等待屏障时超时; 要么
  • 其他一些线程在这个屏障上调用reset()

如果当前线程:

  • 在进入该方法时设置了中断状态; 要么
  • 是等待interrupted

然后InterruptedException被关上,当前线程的中断状态被清除。

如果屏蔽是reset() ,而任何线程正在等待,或者当await被调用时屏障is broken ,或者任何线程等待,则抛出BrokenBarrierException

如果任何线程在等待的时候是interrupted ,那么所有其他等待的线程将会丢失BrokenBarrierException ,并且屏障被置于断开的状态。

如果当前线程是要到达的最后一个线程,并且在构造函数中提供非空障碍操作,则当前线程在允许其他线程继续之前运行该动作。 如果在屏障动作期间发生异常,则该异常将在当前线程中传播,并且屏障置于断开状态。

结果

当前线程的到达索引,其中索引 getParties() - 1表示第一个到达,零表示最后到达

异常

InterruptedException - 如果当前线程在等待时中断

BrokenBarrierException - 如果当前线程正在等待,或者屏蔽被重置,或者当 await时屏障被破坏,或者屏蔽动作(如果存在)由于异常而失败,则 另一个线程被中断或超时

例子:实现abc三个线程同时执行。

public class CyclicBarrierDemo {
    public static void main(String[] args) {

        CBDPrint cbdPrint = new CBDPrint();
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        new Thread(()->{
            try {
                cyclicBarrier.await();
                cbdPrint.printA();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        },"线程A").start();
        new Thread(()->{
            try {
                cyclicBarrier.await();
                cbdPrint.printB();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        },"线程B").start();
        new Thread(()->{
            try {
                cyclicBarrier.await();
                cbdPrint.printB();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        },"线程C").start();
    }
}

class CBDPrint{
    public void printA(){
        System.out.println(Thread.currentThread().getName()+"aaaaaaaaaaaaaaaaa");
    }
    public void printB(){
        System.out.println(Thread.currentThread().getName()+"bbbbbbbbbbbbbbbb");
    }
    public void printC(){
        System.out.println(Thread.currentThread().getName()+"ccccccccccccccccc");
    }
}

多线程常用类

上一篇:Java 多线程(sleep)


下一篇:Day13_67_interrupt() 方法