个人原创,谢谢支持
代码个人编写,实测有效,欢迎转载本文链接。https://blog.csdn.net/u014730287/article/details/103399779
实现原理
启动多线程卖票
使用 ExecutorService executorService = newFixedThreadPool(threadNum); 方法,创建线程池,该创建方法,能够创建固定线程数的线程池。创建线程的几种方法,以后再讲。
创建完成后,使用 executorService.execute(task); 方法,启动线程。
使用内置方法,等待多线程统一结束
- 1 、等待全部线程结束,需要用到CountDownLatch方法,具体代码为CountDownLatch threadSignal = new CountDownLatch(threadNum); threadNum与启动线程数相对应,不然会造成全部线程未结束,后续代码提取启动、或者一直等待死锁问题。
- 2、每个线程执行结束后,都必须调用downLatch.countDown(); 方法,不然那线程计数器不减1,程序一直等待。
- 3、主线程执行** threadSignal.await(120,TimeUnit.SECONDS);** 方法,该方法会等待全部线程结束,然后执行后续代码。又分为有参、无参两种。无参:当线程未执行第二步时,会一直等待,形成死锁;有参:程序会等待相应的时间,超时后自动执行后续代码。
实现代码
启动多线程类
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.Executors.*;
/**
* 多线程测试查看
* @author fkptxmz
*/
public class WatchThread {
private void testExecutor(){
//启动线程数
int threadNum = 9;
//初始化CountDownLatch
CountDownLatch threadSignal = new CountDownLatch(threadNum);
//初始化线程池
ExecutorService executorService = newFixedThreadPool(threadNum);
for (int i = 0; i < threadNum; i++) {
//创建多线程对象
Runnable task = new StationSaleTicket(threadSignal);
// 线程池执行多线程任务
executorService.execute(task);
}
try {
//等待线程全部执行完成,最大等待时间120秒,
// 防止线程未调用countDown()方法,使得程序一直等待,造成死锁
//threadSignal.await(120,TimeUnit.SECONDS);
//设置超时时间为1秒钟,查看超时时,是否会跳过线程等待,执行后续代码
threadSignal.await(1,TimeUnit.SECONDS);
System.out.println("------------>:线程全部结束,可以执行下一步");
} catch (Exception e) {
e.printStackTrace();
}
executorService.shutdown();
}
/**
* 测试方法
*/
public static void main(String[] args){
WatchThread test = new WatchThread();
test.testExecutor();
}
}
卖票代码实现
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
/**
* @author fkptxmz
*/
public class StationSaleTicket implements Runnable {
private CountDownLatch downLatch;
StationSaleTicket(CountDownLatch downLatch) {
this.downLatch = downLatch;
}
/**
* 为了保持票数的一致,票数要静态
*/
private static int totalTicket = 5000;
/**
* 创建一个静态秘钥
*/
private static final String TICKET_KEY = "ticket";
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始...");
// do something
while (totalTicket > 0) {
synchronized (TICKET_KEY) {
if (totalTicket > 0) {
System.out.println(Thread.currentThread().getName() + "卖出了第" + totalTicket + "张票,编号为:" + this.getTicketUuid());
totalTicket--;
} else {
System.out.println(Thread.currentThread().getName() + "票卖完了!!!");
}
}
try {
//线程睡眠
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
//线程睡眠
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 核心处理逻辑
// 用到成员变量name作为参数
// 线程结束时计数器减1
System.out.println(Thread.currentThread().getName() + "结束. 还有" + downLatch.getCount() + " 个线程");
//必须等核心处理逻辑处理完成后才可以减1
downLatch.countDown();
}
/**
* 获取UUID
*
* @return String
*/
private String getTicketUuid() {
return UUID.randomUUID().toString().replace("-", "");
}
}