thread17 - 多线程练习题2

时间:2021-06-28 00:15:12
package com.neutron.t16;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* 淘宝笔试题:
* 实现个容器,提供两个方法,add和size
* 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素个数,当个数到5个的时候,线程2给出提示并且结束
*
* 分析下面程序能否实现要求
*/
public class T163 {
volatile List lists = new ArrayList<>();

public void add(Object obj) {
lists.add(obj);
}

public int size() {
return lists.size();
}

public static void main(String[] args) {
T163 t161 = new T163();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
t161.add(new Object());
System.out.println("add " + i);

try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t1").start();

new Thread(() -> {
while(true) {
if (t161.size() == 5) {
break;
}
}
System.out.println("t2 is over");
}, "t2").start();
}

/**
* 输出结果:
* add 0
add 1
add 2
add 3
add 4
t2 is over
add 5
add 6
add 7
add 8
add 9

这就是我们要的结果,分析程序为何这么执行呢?
线程1执行的时候,不断将list中添加数据,从0到9,然后每增加1个数据,小睡1秒
线程2执行,当线程1小睡的时候,线程1执行,同时线程1和线程2中的list是可见的,
所以线程2获取真正的list,然后判断list长度

注意:如果你将这段代码注释掉,将得不到你想要的结果,下面代码的目的就是为了让线程2执行
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}

上面代码的不足地方:
1.因为没有使用锁,所在当t161.size()等于5的时候,又有个线程执行add操作,此时其实是size等于6才执行操作。
2.线程2的死循环浪费cpu
*/
}