• 多线程学习(十一)


    仿真任务

    装饰花园

    在这个仿真程序中花园委员会想统计每天通过多个门,进入花园的人数,每个门上有个十字转门相当于是计数器。转动任意一扇门就表示公园的分享计数值就会增加一。

    代码如下:

    计数器:

    /**
     * 计数器
     *
     */
    public class Counter {
    	private int value;
    	private Random random = new Random(47);
    
    	public synchronized int increment() {
    		if (random.nextBoolean())
    			Thread.yield();// 给个机会让它切换线程
    		return ++value;
    	}
    
    	public synchronized int getValue() {
    		return value;
    	}
    }
    

    入口:

    public class Entrance implements Runnable {
    	private static Counter counter = new Counter();
    	private static ArrayList<Entrance> stores = new ArrayList<>();
    	private int num;
    	private final int id;
    	private static volatile boolean canceled = false;
    
    	public Entrance(int id) {
    		super();
    		this.id = id;
    		stores.add(this);
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		while (!canceled) {
    			synchronized (this) {
    				++num;
    			}
    
    			System.out.println(this + " total:" + counter.increment());
    			try {
    				TimeUnit.MILLISECONDS.sleep(300);// 模拟一下 不要一直 递增
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    
    		}
    		System.out.println("stop:("+id+") num:"+num);
    	}
    
    	@Override
    	public synchronized String toString() {
    		return "Entrance (" + id + ") num:" + num;
    	}
    
    	public static int getTotal() {
    		return counter.getValue();
    	}
    
    	public static int sum() {
    		int sums = 0;
    		for (Entrance e : stores) {
    			sums += e.num;
    		}
    		return sums;
    	}
    
    	public static void cancel() {
    		canceled = true;
    		/**
    		 * 看过一些资料说对原始类型不包括(long,double)变量进行赋值是原子操作
    		 * d对引用变量的赋值操作是否是原子操作见:https://www.zhihu.com/question/46681046 第二个回答
    		 * 
    		 */
    	}
    }
    

    花园仿真类:

    public class Garden {
    	public static void main(String[] args) {
    		ExecutorService exec = Executors.newCachedThreadPool();
    		for (int a = 0; a < 5; a++) {
    			exec.execute(new Entrance(a));
    		}
    
    		try {
    			TimeUnit.SECONDS.sleep(3);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    		Entrance.cancel();
    
    		exec.shutdown();
    		boolean flag = false;
    		try {
    			flag = exec.awaitTermination(2000, TimeUnit.MILLISECONDS);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		if (!flag)
    			System.out.println("some task don't over.");
    
    		System.out.println("total:" + Entrance.getTotal());
    		System.out.println(" sums:" + Entrance.sum());
    	}
    }
    

    运行结果:

    可以删除上面的程序中的 任意 同步代码块 的 同步修饰 就可以看到程序运行失败的效果。
    程序中 exec.awaitTermination(2000, TimeUnit.MILLISECONDS); 这个方法的意思 是 executorService 在指定的时间中任务全部停止完毕的话 会返回true。否则返回false.

  • 相关阅读:
    20145212 《Java程序设计》第10周学习总结
    20145212 实验五《Java网络编程》
    20145212 《Java程序设计》第9周学习总结
    20145212 实验四《Andoid开发基础》
    《信息安全系统设计基础》第2周总结
    20145210《信息安全系统设计基础》第1周学习总结
    20145210 《信息安全系统设计基础》第0周学习总结
    20145210姚思羽_课程总结
    20145210实验五《Java网络编程》
    20145210 《Java程序设计》第十周学习总结
  • 原文地址:https://www.cnblogs.com/joeCqupt/p/6832998.html
Copyright © 2020-2023  润新知