1.semaphore
控制一个文件允许方法的并发数,即同时访问这个文件的线程数量。
public class TestThread {
public static void main(String[] args) {
//创建线程池
ExecutorService service=Executors.newCachedThreadPool();
//设置最大并发访问次数
final Semaphore sp=new Semaphore(3);
for(int i=0;i<10;i++){
Runnable runnable=new Runnable(){
public void run() {
try {
//获得一个允许
sp.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程"+Thread.currentThread().getName()+
"进入,当前已有"+(3-sp.availablePermits())+"线程");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程"+Thread.currentThread().getName()+"即将离开");
sp.release();
}
};
//执行线程
service.execute(runnable);
}
}
}
控制台执行结果
线程pool-1-thread-1进入,当前已有3线程
线程pool-1-thread-3进入,当前已有3线程
线程pool-1-thread-2进入,当前已有3线程
线程pool-1-thread-3即将离开
线程pool-1-thread-1即将离开
线程pool-1-thread-2即将离开
线程pool-1-thread-4进入,当前已有1线程
线程pool-1-thread-5进入,当前已有2线程
线程pool-1-thread-6进入,当前已有3线程
线程pool-1-thread-5即将离开
线程pool-1-thread-4即将离开
线程pool-1-thread-6即将离开
线程pool-1-thread-8进入,当前已有3线程
线程pool-1-thread-7进入,当前已有3线程
线程pool-1-thread-9进入,当前已有3线程
线程pool-1-thread-8即将离开
线程pool-1-thread-9即将离开
线程pool-1-thread-7即将离开
线程pool-1-thread-10进入,当前已有3线程
线程pool-1-thread-10即将离开
2.CyclicBarrier
所有线程彼此等待,所有线程都执行完一段代码后,在各自执行下面的代码
public class TestThread2 {
public static void main(String[] args) {
//创建线程池
ExecutorService service=Executors.newCachedThreadPool();
//设置同时等待数量
final CyclicBarrier sp=new CyclicBarrier(3);
for(int i=0;i<3;i++){
Runnable runnable=new Runnable(){
public void run() {
try {
Thread.sleep((long)Math.random()*10000);
System.out.println("线程"+Thread.currentThread().getName()+
"进入集合地点1,当前已有"+(sp.getNumberWaiting()+1)+"线程等待,"+ (sp.getNumberWaiting()==3?"都到了,一起走":""));
sp.await();
Thread.sleep((long)Math.random()*10000);
System.out.println("线程"+Thread.currentThread().getName()+
"进入集合地点2,当前已有"+(sp.getNumberWaiting()+1)+"线程等待,"+(sp.getNumberWaiting()==3?"都到了,一起走":""));
sp.await();
} catch (Exception e) {
e.printStackTrace();
}
}
};
//执行线程
service.execute(runnable);
}
}
}
执行结果
线程pool-1-thread-2进入集合地点1,当前已有1线程等待,
线程pool-1-thread-1进入集合地点1,当前已有2线程等待,
线程pool-1-thread-3进入集合地点1,当前已有3线程等待,都到了,一起走
线程pool-1-thread-3进入集合地点2,当前已有1线程等待,
线程pool-1-thread-2进入集合地点2,当前已有1线程等待,
线程pool-1-thread-1进入集合地点2,当前已有3线程等待,都到了,一起走
3.CountDownLatch
倒计时计数器,CountDownLatch对象的countDown方法,将计数器减1,当计数器到达0时候,所有等待者开始执行开始执行。实现一个人等待多个人,或多个人等待一个人
public class CountdownLatchTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CountDownLatch cdOrder = new CountDownLatch(1);
final CountDownLatch cdAnswer = new CountDownLatch(3);
for(int i=0;i<3;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
System.out.println("线程" + Thread.currentThread().getName() +
"正准备接受命令");
cdOrder.await();
System.out.println("线程" + Thread.currentThread().getName() +
"已经接受命令");
Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"等待处理结果");
cdAnswer.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
}
try {
Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"即将发送命令");
cdOrder.countDown();
System.out.println("线程" + Thread.currentThread().getName() +
"线程已经发送命令");
cdAnswer.await();
System.out.println("线程" + Thread.currentThread().getName() +
"已收到响应结果");
} catch (Exception e) {
e.printStackTrace();
}
service.shutdown();
}
}
执行结果
线程pool-1-thread-1正准备接受命令
线程pool-1-thread-3正准备接受命令
线程pool-1-thread-2正准备接受命令
线程main即将发送命令
线程main线程已经发送命令
线程pool-1-thread-2已经接受命令
线程pool-1-thread-1已经接受命令
线程pool-1-thread-3已经接受命令
线程pool-1-thread-1等待处理结果
线程pool-1-thread-3等待处理结果
线程pool-1-thread-2等待处理结果
线程main已收到响应结果
4.Exchange
用于两个线程之间数据交换,一个线程拿出数据要一直等待直到另外一个线程拿出数据,才能交换
public class ExchangerTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final Exchanger exchanger = new Exchanger();
service.execute(new Runnable(){
public void run() {
try {
String data1 = "黄金";
System.out.println("线程" + Thread.currentThread().getName() +
"正准备把" + data1 +"换出");
Thread.sleep((long)(Math.random()*10000));
String data2 = (String)exchanger.exchange(data1);
System.out.println("线程" + Thread.currentThread().getName() +
"换成的数据为" + data2);
}catch(Exception e){
}
}
});
service.execute(new Runnable(){
public void run() {
try {
String data1 = "钻石 ";
System.out.println("线程" + Thread.currentThread().getName() +
"正准备把" + data1 +"换出");
Thread.sleep((long)(Math.random()*10000));
String data2 = (String)exchanger.exchange(data1);
System.out.println("线程" + Thread.currentThread().getName() +
"换成的数据为" + data2);
}catch(Exception e){
}
}
});
}
}
执行结果
线程pool-1-thread-1正准备把zxx换出
线程pool-1-thread-2正准备把lhm换出
线程pool-1-thread-2换成的数据为zxx
线程pool-1-thread-1换成的数据为lhm