例题:
某公司组织年会,会议入场时有两个入口,在入场时每位员工都能获取一张双色球彩票,假设公司有100个员工,利用多线程模拟年会入场过程,并分别统计每个入口入场的人数,以及每个员工拿到的彩票的号码。线程运行后打印格式如下:
编号为: 2 的员工 从后门 入场! 拿到的双色球彩票号码是: [17, 24, 29, 30, 31, 32, 07]编号为: 1 的员工 从后门 入场! 拿到的双色球彩票号码是: [06, 11, 14, 22, 29, 32, 15]
…..
从后门入场的员工总共: 13 位员工
从前门入场的员工总共: 87 位员工
分析问题:
首先,题目明确给出入场以及出场以及入场两个线程,前门进入以及后门进入是同时进行的。
其次这里多个线程同时使用的的共享数据为人数number,两个线程都会对number的值进行修改。所以该线程存在安全问题,需要使用同步代码块把存在线程安全问题的代码锁起来
最后彩票可用Random生成随机数
代码实现
package 双色球彩票;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//定义实现类PeopleThread实现接口Runnable接口并重写run()方法;
public class PeopleThread implements Runnable {
private int number = 1;
private Random ran = new Random();
private int qianmenpeople;
private int houmenpeople;
private String lottery;
private Lock lock = new ReentrantLock();
public void run() {
while (number <= 100) {// 进行循环,人数编号从100-1;
lock.lock();// 上锁
for (int j = 0; j < 7; j++) {// 循环七次,获取七个随机的1-99的数字当作彩票号码
int n = ran.nextInt(99) + 1;
String str;
if (n < 10) {
str = "0" + n;//讲随机数转为String类型,若随机数生成为1-9的数,则改为01,02...
} else {
str = "" + n;//
}
if (j == 0) {//定义彩票输出格式
lottery = "[" + str + " ";
} else if (j == 6) {
lottery = lottery + str + "]";
} else {
lottery = lottery + str + " ";
}
}
System.out.println(
"编号为:" + number + "_的员工 从" + Thread.currentThread().getName() + " 入场!" + "拿到的双色球彩票号码是:" + lottery);
if (Thread.currentThread().getName().equals("前门")) {
qianmenpeople++;//这里需要统计前门线程执行的次数
}
if (Thread.currentThread().getName().equals("后门")) {
houmenpeople++;//这里需要统计后门线程执行的次数
}
number++;//线程执行结束后人数-1;
lock.unlock();//释放锁
try {
Thread.sleep(100);//延时100毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (Thread.currentThread().getName().equals("前门")) {
System.out.println("从" + Thread.currentThread().getName() + "入场的员工总共:" + qianmenpeople + " 位员工");
}
if (Thread.currentThread().getName().equals("后门")) {
System.out.println("从" + Thread.currentThread().getName() + "入场的员工总共:" + houmenpeople + " 位员工");
}
}
}
//定义测试类Test
public class Test {
public static void main(String[] args) {
PeopleThread pt = new PeopleThread();
new Thread(pt,”前门”).start();
new Thread(pt,”后门”).start();
}
}
输出结果:
总结
遇到需要共同执行的线程时首先需判断线程是否存在安全问题,
存在安全问题:
1.是否为多线程环境
2.是否存在共享数据
3.是否存在多条语句共同执行
如何实现没有安全问题环境:
把多个语句操作共享数据的代码锁起来,让任意时刻只能有一个线程执行即可