• ccse(CountDownLatch,CycliBarrier,Semaplore,Exchanger)


    关于等待状态的线程调用interrupt方法报异常:InterruptedException

    当线程被阻塞,比如wait,join,sleep等,在调用interrupt方法,没有占用cpu运行的线程是不可能给自己的中断状态置位的,这就产生了InterruptedException异常.

    一.闭锁CountDownLatch(允许一个或多个线程等待其它线程完成操作)

    代码实例:

    package com.thread.ccse;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Created by IntelliJ IDEA.
     * User: 周强
     * Description:
     * Date: 2017/8/9
     * Time: 21:04
     */
    public class CountDownLatchTest {
        public static CountDownLatch c = new CountDownLatch(4);
        public static void main(String [] args) throws InterruptedException {
            Thread t =new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(c.getCount()); //第1
                    c.countDown();
                    System.out.println(c.getCount());//第2
                    c.countDown();
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(c.getCount());//第3
                    c.countDown();
                    System.out.println(c.getCount());//第4
                }
            });
            t.start();
            c.await(2, TimeUnit.SECONDS);
            c.countDown();
            System.out.println(c.getCount( ));//第5
        }
    }
    

      输出结果如下:

    Connected to the target VM, address: '127.0.0.1:55816', transport: 'socket'
    4      第1
    3      第2
    1      第5
    Disconnected from the target VM, address: '127.0.0.1:55816', transport: 'socket'
    1      第3
    0      第4
    
    Process finished with exit code 0
    

      由于线程t沉睡时间大于CountDownLatch c的等待时间,所以线程t在主线证执行完毕后才结束的.

    二:栅栏CyclicBarrier(指定线程数,必须在该线程数内的线程全部到达同步点,才继续往下执行)

    示例代码:

    package com.thread.ccse;
    
    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;
    
    /**
     * Created by IntelliJ IDEA.
     * User: 周强
     * Description:
     * Date: 2017/8/9
     * Time: 21:30
     */
    public class CyclicBarrierTest {
    
        static Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("3");
            }
        });
    
        static  Thread thread = null;
        public static CyclicBarrier c = new CyclicBarrier(2,t);
        static {
            thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        c.await();
                        System.out.println("1");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    
    
    
    
        public static void main(String [] args){
    
            thread.start();
            try {
                c.await();
                System.out.println("2");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    
    }
    

     执行结果:

    Disconnected from the target VM, address: '127.0.0.1:56157', transport: 'socket'
    3
    2
    1//其中,3 肯定是最先输出的,1 和 2 的输出顺序是不一定的 
    
    Process finished with exit code 0
    

      

    CountDownLatch和CyclicBarrier的区别:

    CountDownLatch计数器只能使用一次,而CyclicBarrier的计数器可以使用多次,因为CyclicBarrier可以使用reset方法重置计数器;

    CyclicBarrier还提供其它方法,如getNumberWating方法可以获得CyclicBarrier阻塞的线程数,isBroken方法可以用来了解阻塞的线程是否被中断。

    三:有界容器Semaphore(构造固定长度的资源池)

    代码示例:

    package com.thread;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.Semaphore;
    
    /**
     * Created by 周强 on 2017/8/10.
     */
    public class SemaphoreTest {
        public static  Semaphore s = new Semaphore(1);
        public static volatile int i =1;
        public static  List<String>  list = new ArrayList();
    
        public static void main(String [] args) throws InterruptedException {
            Thread a = new Thread(new ta());
            Thread b = new Thread(new tb());
    
            s.acquire();  //消费唯一许可;
            a.start();
            b.start();
    
        }
    
        static class ta implements Runnable{
            @Override
            public void run() {
                System.out.println("开始");
                try {
                    s.acquire();   //唯一许可已被消费了,此处被阻塞
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(i);
                list.add(String.valueOf(i));
                i++;
                System.out.println("开始---end");
    
            }
        }
        static class tb implements Runnable{
            @Override
            public void run() {
                System.out.println("acquire");
                list.remove(String.valueOf(i));
                System.out.println(list.toString());
                s.release();、//释放许可
            }
        }
    }
    

      执行结果:

    Disconnected from the target VM, address: '127.0.0.1:65218', transport: 'socket'
    开始
    acquire
    []
    1
    开始---end
    
    Process finished with exit code 0
    

    四.(线程同步)Exchanger()

    代码示例:

    package com.thread;
    
    import java.util.concurrent.Exchanger;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * Created by 周强 on 2017/8/10.
     */
    public class ExchangerTest {
        public static Exchanger<String> exgr = new Exchanger<String>();
        public static ExecutorService threadPool = Executors.newFixedThreadPool(2);
    
        public static void main(String [] args){
            threadPool.execute(new Runnable() {   //线程A
                @Override
                public void run() {
                    String a = "a";
    
                    try {
                        exgr.exchange(a);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("a  ="+a );
                }
            });
            threadPool.execute(new Runnable() {  //线程B
    @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } String b = "b"; String a = null; try { a = exgr.exchange("b"); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("a ="+a +" "+"b ="+b); } }); threadPool.shutdown(); } }

      执行结果:

    结果一:
    Connected to the target VM, address: '127.0.0.1:49408', transport: 'socket' a =a b =b
    a =a Disconnected from the target VM, address: '127.0.0.1:49408', transport: 'socket'

    结果二:
    Connected to the target VM, address: '127.0.0.1:49524', transport: 'socket'
    a =a
    a =a b =b
    Disconnected from the target VM, address: '127.0.0.1:49524', transport: 'socket'
    结论:虽然线程B沉睡了1秒,但由于线程A和B都在exgr.exchange处阻塞了,互相等待,且阻塞后的只剩下了打印的操作,所以,打印操作的先后顺序并能确定.

      

     Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。

    以上为本次学习   闭锁(CountDownLatch),栅栏(CyclicBarrier),有界容器(Semaphore)和线程同步工具类(Exchange)四个多线程相关工具类的代码笔记,工作中没有使用过,权且学习积累,以备后用。

    //线程A
  • 相关阅读:
    Ubuntu16.04 中 Vscode 如何断点调试C语言程序
    PHP疑难杂症
    PHP之外观模式
    23种设计模式之适配器模式(Adapter Pattern)
    23种设计模式之原型模式(Prototype Pattern)
    23种设计模式之单例(Singleton Pattern)
    23种设计模式之抽象工厂(Abstract Factory Pattern)
    23种设计模式之工厂方法(Factory Method Pattern)
    简单工厂
    Nosql之Redis
  • 原文地址:https://www.cnblogs.com/zqsky/p/7328013.html
Copyright © 2020-2023  润新知