JAVA多线程并发同步,以及线程终止

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://xxlcube.blog.csdn.net/article/details/8574048
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

class Count {
	private int count = 0;
	//private Random rand = new Random(10);
	public synchronized int increment() {
		return ++count;
	}
	public synchronized int getCount() {
		return count;
	}
}

class Entrance implements Runnable {

	private static Count count = new Count();
	private static List<Entrance> entrances = new ArrayList<Entrance>();
	private int number = 0;
	private final int id;
	private static volatile boolean canceled = false;
	public static void cancel() {
		canceled = true;
	}
	public Entrance(int id) {//id表示花园有多少个入口
		this.id = id;
		entrances.add(this);
	}
	
	public void run() {
		while(!canceled) {//没有cancel,就一直运行
			synchronized (this) {//this-->Entrance,对Entrance对象加锁了
				++number;
			}
			System.out.println(this+",总共进入花园人数->"+count.increment());
			try {
				TimeUnit.MILLISECONDS.sleep(100);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		System.out.println("Stopping "+this);
	}
	public synchronized int getValue() {//获取单个花园入口的人数
		return number;
	}
	public String toString() {
		return "花园入口"+id+"号进入人数->"+getValue();
	}
	public static int getTotalCount() {
		return count.getCount();
	}
	public static int sumEntrances() {
		int sum = 0;
		for(Entrance entrance:entrances) {
			sum+=entrance.getValue();
		}
		return sum;
	}
}

public class GardenPeople {

	public static void main(String[] args) throws Exception {
		ExecutorService es = Executors.newCachedThreadPool();
		for(int i=0;i<5;i++) {
			es.execute(new Entrance(i));
		}
		TimeUnit.MILLISECONDS.sleep(500);
		Entrance.cancel();
		//启动一次顺序关闭,执行以前提交的任务,但不接受新任务,execute提交的任务都会关闭
		es.shutdown();
		if(!es.awaitTermination(250, TimeUnit.MILLISECONDS)) {
			System.out.println("Some tasks were not terminated !");
		}
		System.out.println("Total : "+Entrance.getTotalCount());
		System.out.println("Sum of Entrances : "+Entrance.sumEntrances());
	}

}

上面的例子是摘自《JAVA编程思想》

很好的一个例子,内容就是,一个花园,有多个入口,现在需要通过多线程来记录通过不同的入口进来,最终一共有多少人员进入了该花园。

volatile修饰符是为了确保该变量在同一时间只能有一个线程去访问,当然这种方法肯定没有synchronized更好。

在主函数中,通过一个循环,new出了花园的所有入口,通过字段id来表示花园入口。

在类Entrance类中,我们可以看到很多字段,number是用来表示该入口的进入人数的总数。每new一个Entrance,number=0

count是一个Count对象,用来表示目前为止,一共进入花园的人数总数,所有的入口都算。为什么能做到这样呢,上面的number每次都是0,而这里的count却可以不断的累加,就是因为count用了static来修饰了,所以它只要new了第一次,后面就不会再new了。它不依赖于类特定的实例,被类的所有实例共享。

 

下面是运行结果:

花园入口0号进入人数->1,总共进入花园人数->1

花园入口2号进入人数->1,总共进入花园人数->3

花园入口1号进入人数->1,总共进入花园人数->2

花园入口3号进入人数->1,总共进入花园人数->4

花园入口4号进入人数->1,总共进入花园人数->5

花园入口0号进入人数->2,总共进入花园人数->6

花园入口2号进入人数->2,总共进入花园人数->9

花园入口4号进入人数->2,总共进入花园人数->10

花园入口1号进入人数->2,总共进入花园人数->7

花园入口3号进入人数->2,总共进入花园人数->8

花园入口1号进入人数->3,总共进入花园人数->11

花园入口3号进入人数->3,总共进入花园人数->15

花园入口2号进入人数->3,总共进入花园人数->14

花园入口4号进入人数->3,总共进入花园人数->13

花园入口0号进入人数->3,总共进入花园人数->12

花园入口2号进入人数->4,总共进入花园人数->16

花园入口4号进入人数->4,总共进入花园人数->19

花园入口0号进入人数->4,总共进入花园人数->20

花园入口3号进入人数->4,总共进入花园人数->18

花园入口1号进入人数->4,总共进入花园人数->17

花园入口0号进入人数->5,总共进入花园人数->21

花园入口2号进入人数->5,总共进入花园人数->23

花园入口3号进入人数->5,总共进入花园人数->22

花园入口1号进入人数->5,总共进入花园人数->25

花园入口4号进入人数->5,总共进入花园人数->24

花园入口2号进入人数->6,总共进入花园人数->27

花园入口1号进入人数->6,总共进入花园人数->28

花园入口3号进入人数->6,总共进入花园人数->26

花园入口4号进入人数->6,总共进入花园人数->30

花园入口0号进入人数->6,总共进入花园人数->29

Stopping 花园入口0号进入人数->6

Stopping 花园入口2号进入人数->6

Stopping 花园入口3号进入人数->6

Stopping 花园入口1号进入人数->6

Stopping 花园入口4号进入人数->6

Total : 30

Sum of Entrances : 30

从结果中,我们可以很清楚的看到,并发同步的过程,还有线程的终止shutdown()。

 

 

 

 

 

 

 

 

 

 

 


 

展开阅读全文

没有更多推荐了,返回首页