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
posted @ 2017-08-09 22:27  it馅儿包子  阅读(669)  评论(0编辑  收藏  举报