线程装饰性花园练习问题总结
在做练习17的时候遇到一个问题,做下记录,代码如下:
public class Test17 {
static class Count {
public int count = 0;
Random random = new Random(47);
public synchronized int increamcount() {
int temp = count;
while (random.nextBoolean()) {
Thread.yield();
}
return count = ++temp;
}
public synchronized int totalCount() {
return count;
}
}
static class Sensor implements Runnable{
private int number = 0;
private static Count count = new Count();
private final int id;
private static List<Sensor> sensorList = new ArrayList<>();
public Sensor(int i) {
id = i;
sensorList.add(this);
}
public static void cancel() {
canceled = true;
}
private static volatile boolean canceled = false;
@Override
public void run() {
while (!canceled) {
synchronized (this) {
number++;
// count.increamcount();
}
// System.out.println(this + " total : " + count.totalCount());
//不能用以上注释掉的写法,因为在执打印的之前,count.increamcount()方法有可能被其他线程执行多次,所以会出现多个相同的count的结果
System.out.println(this + " total : " + count.increamcount());
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
System.out.println("sleep interrupted");
}
}
System.out.println("stopping " + this);
}
public String toString() {
return "Sensor " + id + " : " + getValue();
}
public synchronized int getValue() {
return number;
}
public static int getTotalValue() {
return count.totalCount();
}
public static int sumEntrances() {
int sum = 0;
for(Sensor sensor : sensorList) {
sum += sensor.getValue();
}
return sum;
}
}
public static void main(String[] args) {
ExecutorService executor =
new ThreadPoolExecutor(1,17,60L,TimeUnit.MILLISECONDS,new SynchronousQueue<>());
for (int i = 0; i < 5; i++) {
executor.execute(new Sensor(i));
}
try {
TimeUnit.SECONDS.sleep(10);
Sensor.cancel();
executor.shutdown();
if(!executor.awaitTermination(250,TimeUnit.MILLISECONDS)) {
System.out.println("Some tasks were not terminated");
}
System.out.println("total :" + Sensor.getTotalValue());
System.out.println("Sum of sensor :" + Sensor.sumEntrances());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在我刚开始的写法中
@Override
public void run() {
while (!canceled) {
synchronized (this) {
number++;
count.increamcount();
//为了结果更清晰
System.out.println(this + " !!!!!!!");
}
System.out.println(this + " total : " + count.totalCount());
//不能用以上注释掉的写法,因为在执打印的之前,count.increamcount()方法有可能被其他线程执行多次,所以会出现多个相同的count的结果
// System.out.println(this + " total : " + count.increamcount());
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
System.out.println("sleep interrupted");
}
}
System.out.println("stopping " + this);
}
打印结果为:
Sensor 0 : 1 !!!
Sensor 2 : 1 !!!
Sensor 1 : 1 !!!
Sensor 4 : 1 !!!
Sensor 3 : 1 !!!
Sensor 4 : 1 total : 5
Sensor 1 : 1 total : 5
Sensor 2 : 1 total : 5
Sensor 0 : 1 total : 5
Sensor 3 : 1 total : 5
Sensor 3 : 2 !!!
Sensor 0 : 2 !!!
Sensor 0 : 2 total : 10
Sensor 2 : 2 !!!
Sensor 2 : 2 total : 10
Sensor 1 : 2 !!!
Sensor 1 : 2 total : 10
Sensor 3 : 2 total : 10
Sensor 4 : 2 !!!
Sensor 4 : 2 total : 10
Sensor 4 : 3 !!!
Sensor 4 : 3 total : 14
Sensor 2 : 3 !!!
Sensor 2 : 3 total : 15
Sensor 3 : 3 !!!
Sensor 3 : 3 total : 15
Sensor 0 : 3 !!!
Sensor 0 : 3 total : 15
Sensor 1 : 3 !!!
Sensor 1 : 3 total : 15
Sensor 2 : 4 !!!
Sensor 4 : 4 !!!
Sensor 4 : 4 total : 20
Sensor 0 : 4 !!!
Sensor 0 : 4 total : 20
Sensor 3 : 4 !!!
Sensor 3 : 4 total : 20
Sensor 1 : 4 !!!
Sensor 1 : 4 total : 20
Sensor 2 : 4 total : 20
Some tasks were not terminated
total :20
Sum of sensor :20
stopping Sensor 3 : 4
stopping Sensor 4 : 4
stopping Sensor 2 : 4
stopping Sensor 1 : 4
stopping Sensor 0 : 4
可以很清晰的看到在第一次sleep,在执行 System.out.println(this + " total : " + count.totalCount());前5个线程已经完成了增加操作。
其中会出现total重复的情况,经过排查,修改如下
//
@Override
public void run() {
while (!canceled) {
synchronized (this) {
number++;
// count.increamcount();
}
// System.out.println(this + " total : " + count.totalCount());
//不能用以上注释掉的写法,因为在执打印的之前,count.increamcount()方法有可能被其他线程执行多次,所以会出现多个相同的count的结果
System.out.println(this + " total : " + count.increamcount());
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
System.out.println("sleep interrupted");
}
}
System.out.println("stopping " + this);
}
打印结果:
Sensor 0 : 1 total : 1
Sensor 4 : 1 total : 5
Sensor 3 : 1 total : 4
Sensor 2 : 1 total : 3
Sensor 1 : 1 total : 2
Sensor 1 : 2 total : 6
Sensor 0 : 2 total : 7
Sensor 4 : 2 total : 10
Sensor 2 : 2 total : 9
Sensor 3 : 2 total : 8
Sensor 4 : 3 total : 11
Sensor 3 : 3 total : 12
Sensor 0 : 3 total : 13
Sensor 1 : 3 total : 14
Sensor 2 : 3 total : 15
Sensor 4 : 4 total : 16
Sensor 3 : 4 total : 17
Sensor 0 : 4 total : 18
Sensor 1 : 4 total : 19
Sensor 2 : 4 total : 20
Some tasks were not terminated
total :20
Sum of sensor :20
stopping Sensor 4 : 4
stopping Sensor 3 : 4
stopping Sensor 0 : 4
stopping Sensor 1 : 4
stopping Sensor 2 : 4