一、卖票
需求:三个人卖30张票
代码:
package com.lee.juc.concurrent;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SaleTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(new Runnable() {
public void run() {
for(int i=0;i<100;i++) {
ticket.sale();
}
}
},"AA").start();
new Thread(new Runnable() {
public void run() {
for(int i=0;i<100;i++) {
ticket.sale();
}
}
},"BB").start();
new Thread(new Runnable() {
public void run() {
for(int i=0;i<100;i++) {
ticket.sale();
}
}
},"CC").start();
}
}
//票
class Ticket{
private int num=30;
private Lock lock = new ReentrantLock();
public void sale() {
lock.lock();
try {
if(num>0) {
System.out.println(Thread.currentThread().getName()+".....sale ticket number : "+num--);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
用lambda写:
package com.lee.juc.concurrent;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SaleTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(()->{for(int i=0;i<100;i++) {ticket.sale();}},"AA").start();
new Thread(()->{for(int i=0;i<100;i++) {ticket.sale();}},"BB").start();
new Thread(()->{for(int i=0;i<100;i++) {ticket.sale();}},"CC").start();
}
}
//票
class Ticket{
private int num=30;
private Lock lock = new ReentrantLock();
public void sale() {
lock.lock();
try {
if(num>0) {
System.out.println(Thread.currentThread().getName()+".....sale ticket number : "+num--);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
二、Callable
代码:
package com.lee.juc.concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* 在主线程中需要执行比较耗时的操作,但又不想阻塞主线程时.可以把这些对象交给Future对象在后台执行,当主线程需要时,
* 就可以通过Future对象获得后台作业计算的结果或者执行状态.
*
* 一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果.
*
* 仅在计算完成时才能检索结果,如果计算尚未完成,则阻塞get方法.一旦计算完成,就不能再重新开始或取消计算.
* get方法获取结果只有在计算完成时获取,否则会一直阻塞到任务转入完成状态,然后会返回结果或者抛出异常.
*
*/
public class CallableDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
FutureTask<Integer> futureTak = new FutureTask<>(new MyThread());
new Thread(futureTak, "AA").start();
new Thread(futureTak, "BB").start();
System.out.println("...this is main method : "+Thread.currentThread().getName());
Integer aResult = futureTak.get();
System.out.println("A---->"+aResult);
Integer bResult = futureTak.get();
System.out.println("B---->"+aResult);
}
}
class MyThread implements Callable<Integer>{
public Integer call() throws Exception {
System.out.println("this is...call...method : "+Thread.currentThread().getName());
Thread.sleep(3000);
return 300;
}
}
三、线程池
代码:
package com.lee.juc.concurrent;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class ExecutorDemo {
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
ScheduledFuture<Integer> scheduledFuture = null;
try {
for (int i = 0; i < 10; i++) {
scheduledFuture = scheduledExecutorService.schedule(()->{
System.out.print(Thread.currentThread().getName()+"...");
return new Random().nextInt(10);
}, 2, TimeUnit.SECONDS);
System.out.println("...."+scheduledFuture.get());
}
} catch (Exception e) {
e.printStackTrace();
}finally {
scheduledExecutorService.shutdown();
}
}
private static void ExecutorService() {
// ExecutorService executorService = Executors.newFixedThreadPool(5);
// ExecutorService executorService = Executors.newSingleThreadExecutor();
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> future = null;
try {
for(int i=0;i<10;i++) {
future = executorService.submit(()->{
System.out.print(Thread.currentThread().getName()+"...");
return new Random().nextInt(10);
});
System.out.println("...."+future.get());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}
}
四、CountDownLatch
代码:
package com.lee.juc.concurrent;
public enum CountryEnum {
ONE(1,"韩"),TWO(2,"赵"),THREE(3,"燕"),FOUR(4,"魏"),FIVE(5,"楚"),SIX(6,"齐");
private Integer code;
private String message;
private CountryEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public static CountryEnum foreachCountryEnums(Integer index) {
for(CountryEnum countryEnum : values()) {
if(countryEnum.getCode() == index) {
return countryEnum;
}
}
return null;
}
}
//=================================================================
package com.lee.juc.concurrent;
import java.util.concurrent.CountDownLatch;
/**
* 让一些线程阻塞直到另一些线程完成后,才被唤醒
*
* 6国被灭后,秦才一统华夏
*/
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t国被灭");
latch.countDown();
}, CountryEnum.foreachCountryEnums(i).getMessage()).start();
}
latch.await();
System.out.println(Thread.currentThread().getName()+"....."+"秦灭六国,一统华夏");
}
}
五、Semaphore
代码:
package com.lee.juc.concurrent;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* 在信号量上我们定义两种操作:
* acquire(获取),当一个线程调用acquire操作时,他要么成功通过获取信号量(信号量减1),要么一直等下去,直到有线程释放信号量,或超时.
* release(释放),实际上会将信号量的值加1,然后唤醒等待的线程.
*
* 信号量主要用于两个目的:
* 一个是用于共享资源的互斥.
* 另一个是用于并发线程的控制.
*
* eg:模拟6辆车,抢3个停车位.
*
*/
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);//模拟三个车位
for (int i = 0; i < 6; i++) { //模拟6辆车
try {
new Thread(()->{
try {
semaphore.acquire();//占领车位
System.out.println(Thread.currentThread().getName()+" 占领车位...");
TimeUnit.SECONDS.sleep(new Random().nextInt(5));//占领一段时间
System.out.println("...."+Thread.currentThread().getName()+"离开车位");
} catch (Exception e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}, String.valueOf(i)).start();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}
}
六、CyclicBarrier
代码:
package com.lee.juc.concurrent;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
/**
* cyclic可循环的 barrier栅栏、屏障
* 让一组线程达到屏障时(阻塞点)被阻塞,直到最后一个线程也达到了屏障时,屏障才会打开,所有被屏障的线程才会继续干活。
*
* eg:集齐七颗龙珠,召唤神龙
*/
public class CyclicBarrierDemo {
private static final Integer NUMBER = 7;
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, ()->{System.out.println("召唤神龙!");});
for (int i = 0; i < NUMBER; i++) {
Integer temp = i;
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(new Random().nextInt(5));//手机龙珠的过程
System.out.println(Thread.currentThread().getName()+"\t收集到第"+temp+"颗龙珠");
cyclicBarrier.await();//等着其他龙珠被收集
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
来源:oschina
链接:https://my.oschina.net/u/3551274/blog/1814060