• 多线程学习(十五)


    仿真

    多线程的优点之一就是仿真:
    银行仿真:

    package bank;
    
    public class Customer {
    	private final int serverTime;
    
    	public Customer(int serverTime) {
    		this.serverTime = serverTime;
    	}
    
    	@Override
    	public String toString() {
    		return " [serverTime=" + serverTime + "] ";
    	}
    
    	public int getServerTime() {
    		return serverTime;
    	}
    
    }
    
    package bank;
    
    import java.util.concurrent.ArrayBlockingQueue;
    
    public class CustomerLine extends ArrayBlockingQueue<Customer> {
    
    	public CustomerLine(int size) {
    		super(size);
    	}
    
    	@Override
    	public String toString() {
    		if (this.size() == 0) { // 这里获取 size 是线程安全的
    			return "CustomerLine []";
    		}
    		StringBuilder sb = new StringBuilder();
    		for (Customer c : this) { // 这里的遍历也是线程安全的
    			sb.append(c);
    		}
    		return sb.toString();
    	}
    
    }
    
    
    package bank;
    
    import java.util.Random;
    import java.util.concurrent.TimeUnit;
    
    public class CustomerGenerator implements Runnable {
    	private CustomerLine cl;
    	private Random random = new Random();
    
    	public CustomerGenerator(CustomerLine cl) {
    		super();
    		this.cl = cl;
    	}
    
    	@Override
    	public void run() {
    		try {
    			while (!Thread.interrupted()) {
    				TimeUnit.MILLISECONDS.sleep(random.nextInt(200));
    				cl.put(new Customer(random.nextInt(1000)));
    			}
    		} catch (InterruptedException ie) {
    			System.out.println("Generator intrrupt");
    		}
    	}
    
    }
    
    package bank;
    
    import java.util.concurrent.TimeUnit;
    
    public class Teller implements Runnable, Comparable<Teller> {
    
    	private int servicedNums;
    	private CustomerLine line;
    	private static int count = 0;
    	private final int id = ++count;
    	private boolean service = true;
    
    	public Teller(CustomerLine line) {
    		super();
    		this.line = line;
    	}
    
    	@Override
    	public int compareTo(Teller otherTeller) {
    		return otherTeller.servicedNums < this.servicedNums ? -1
    				: (otherTeller.servicedNums > this.servicedNums ? 1 : 0);
    	}
    
    	@Override
    	public void run() {
    		try {
    			while (!Thread.interrupted()) {
    				Customer c = line.take();
    				TimeUnit.MILLISECONDS.sleep(c.getServerTime());
    				synchronized (this) {
    					servicedNums++;
    					if (!service) {
    						wait();
    					}
    				}
    			}
    		} catch (InterruptedException ie) {
    			System.out.println(this + " interrupt");
    		}
    	}
    
    	@Override
    	public String toString() {
    		return "Teller [id=" + id + "]";
    	}
    
    	public synchronized void doSomeThingElse() {
    		service = false;
    	}
    
    	public synchronized void serviceTheLine() {
    		service = true;
    		notifyAll();
    	}
    }
    
    
    package bank;
    
    import java.util.LinkedList;
    import java.util.PriorityQueue;
    import java.util.Queue;
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class TellerManager implements Runnable {
    	private PriorityQueue<Teller> workingQueue = new PriorityQueue<>();
    	private Queue<Teller> doSomeElseQueue = new LinkedList<>();
    	private int period;
    	private Random random = new Random();
    	private CustomerLine line;
    	private ExecutorService exec;
    
    	public TellerManager(int period, CustomerLine line, ExecutorService exec) {
    		super();
    		this.period = period;
    		this.line = line;
    		this.exec = exec;
    		Teller teller = new Teller(line);
    		workingQueue.add(teller);
    		exec.execute(teller);
    	}
    
    	public void ajustTellerNum() {
    		if (line.size() / workingQueue.size() > 2) {
    			if (doSomeElseQueue.size() > 0) {
    				Teller teller = doSomeElseQueue.remove();
    				teller.serviceTheLine();
    				workingQueue.add(teller);
    				return;// 不用向下执行了
    			}
    			Teller teller = new Teller(line);
    			exec.execute(teller);
    			workingQueue.add(teller);
    			return;
    		}
    		if (workingQueue.size() > 1 && line.size() / workingQueue.size() < 2) {
    			removeOneTeller();
    		}
    		if (line.size() == 0) {
    			while (workingQueue.size() > 0) {
    				removeOneTeller();
    			}
    		}
    
    	}
    
    	private void removeOneTeller() {
    		Teller teller = workingQueue.poll();
    		teller.doSomeThingElse();
    		doSomeElseQueue.offer(teller);
    	}
    
    	@Override
    	public void run() {
    		try {
    			while (!Thread.interrupted()) {
    				TimeUnit.MILLISECONDS.sleep(period);
    				ajustTellerNum();
    				System.out.println("{ line: " + line);
    				StringBuilder sb = new StringBuilder();
    				for (Teller t : workingQueue) {
    					sb.append(t);
    				}
    				System.out.println("teller: " + sb.toString()+"}");
    			}
    		} catch (InterruptedException ie) {
    			System.out.println("tellermanager intrrupt");
    		}
    	}
    
    }
    
    package bank;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    public class BankTest {
    	public static void main(String[] args) throws InterruptedException {
    		CustomerLine line=new CustomerLine(30);
    		ExecutorService exec=Executors.newCachedThreadPool();
    		exec.execute(new CustomerGenerator(line));
    		exec.execute(new Teller(line));
    		exec.execute(new TellerManager(600, line, exec));
    		TimeUnit.MILLISECONDS.sleep(6000);
    		exec.shutdownNow();
    	}
    }
    
    
    输出结果:
    { line:  [serverTime=899]  [serverTime=705]  [serverTime=227]  [serverTime=950] 
    teller: Teller [id=2]Teller [id=3]}
    { line:  [serverTime=227]  [serverTime=950]  [serverTime=491]  [serverTime=320]  [serverTime=881]  [serverTime=229]  [serverTime=737]  [serverTime=153] 
    teller: Teller [id=2]Teller [id=3]Teller [id=4]}
    { line:  [serverTime=737]  [serverTime=153]  [serverTime=593]  [serverTime=54]  [serverTime=792]  [serverTime=860]  [serverTime=228]  [serverTime=702] 
    teller: Teller [id=2]Teller [id=3]Teller [id=4]}
    { line:  [serverTime=228]  [serverTime=702]  [serverTime=168]  [serverTime=251]  [serverTime=62]  [serverTime=206]  [serverTime=38]  [serverTime=715] 
    teller: Teller [id=2]Teller [id=3]Teller [id=4]}
    { line:  [serverTime=62]  [serverTime=206]  [serverTime=38]  [serverTime=715]  [serverTime=307]  [serverTime=173]  [serverTime=758]  [serverTime=857]  [serverTime=570]  [serverTime=657]  [serverTime=467]  [serverTime=382]  [serverTime=35] 
    teller: Teller [id=2]Teller [id=3]Teller [id=4]Teller [id=5]}
    { line:  [serverTime=467]  [serverTime=382]  [serverTime=35]  [serverTime=333]  [serverTime=355]  [serverTime=996]  [serverTime=738] 
    teller: Teller [id=3]Teller [id=5]Teller [id=4]}
    { line:  [serverTime=355]  [serverTime=996]  [serverTime=738]  [serverTime=130]  [serverTime=149]  [serverTime=448]  [serverTime=595]  [serverTime=504] 
    teller: Teller [id=3]Teller [id=5]Teller [id=4]}
    { line:  [serverTime=504]  [serverTime=876]  [serverTime=416]  [serverTime=837]  [serverTime=563]  [serverTime=747]  [serverTime=372] 
    teller: Teller [id=3]Teller [id=5]Teller [id=4]}
    { line:  [serverTime=563]  [serverTime=747]  [serverTime=372]  [serverTime=2]  [serverTime=160]  [serverTime=880]  [serverTime=271]  [serverTime=571]  [serverTime=47] 
    teller: Teller [id=3]Teller [id=5]Teller [id=4]Teller [id=2]}
    Generator intrrupt
    Teller [id=2] interrupt
    Teller [id=1] interrupt
    Teller [id=3] interrupt
    tellermanager intrrupt
    Teller [id=5] interrupt
    Teller [id=4] interrupt
    
    
  • 相关阅读:
    GateWay配置使用
    Hystrix&Dashboard配置使用
    Ribbon&OpenFeign配置使用
    服务端&客户端注册进Eureka
    Eureka单机&集群配置
    通过淘宝IP库获取定位
    php 红包瓜分算法(实用)
    换博客力!
    2021 上学期做题记录
    计数 DP 学习笔记
  • 原文地址:https://www.cnblogs.com/joeCqupt/p/6858523.html
Copyright © 2020-2023  润新知