新类库中的构件
CountDownLatch
- 可以向CountDownLatch对象设置一个初始计数值,任何对象在这个对象上调用await()方法都将阻塞,直至这个计数值为0(如果一开始就是0那就不用等待)。我们通过其他任务在这个对象上调用countDown()来缩小这个计数值(最多减到0)。这个构件的意义就是设置一些任务必须在n个任务都完成的情况下才可以执行。
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchDemo {
static final int SIZE = 100;
public static void main(String args[]) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool();
CountDownLatch latch = new CountDownLatch(SIZE);
for (int i=0; i<10; i++) {
exec.execute(new WaitingTask(latch));
}
for (int i=0; i<SIZE; i++) {
exec.execute(new TaskPortion(latch));
}
System.out.println("Launched all tasks");
exec.shutdown();
}
}
class TaskPortion implements Runnable {
private static int counter = 1;
private static Random rand = new Random(47);
private final int id = counter++;
private final CountDownLatch latch;
public TaskPortion(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
Thread.sleep(rand.nextInt(2000));
System.out.println(this + "completed");
latch.countDown();
System.out.println(latch.getCount());
} catch (InterruptedException e) {}
}
public String toString() {
return String.format("%-3d ", id);
}
}
class WaitingTask implements Runnable {
private static int counter = 1;
private final int id = counter++;
private final CountDownLatch latch;
public WaitingTask(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
latch.await();
System.out.println("Latch barrier passed for " + this);
} catch (InterruptedException e) {
System.out.println(this + "interrupted");
}
}
public String toString() {
return String.format("WaitingTask %-3d ", id);
}
}
- 程序运行后,10个WaitingTask任务将等待,直到100个TaskPortion全部执行完毕再开始执行。
CyclicBarrier
- CyclicBarrier适用于你希望创建一组任务,它们并行执行,然后在进行下一个步骤之前等待,直至所有任务都完成。它使得所有的并行任务都将在栅栏处列队,因此可以一致地向前运动。它与CountDownLatch的区别是,后者是只触发一次的事件,而它可以多次重用。下面是我模仿书上赛马的程序写的一个关于加载的程序:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 模拟LOL要10个人才能开始游戏
* 每次必须满10个人一起加载一次,当加载量都为100时,游戏开始
*/
public class PlayGame {
public static ExecutorService exec = Executors.newCachedThreadPool();
public static List<Player> players = new ArrayList<Player>();
public static CyclicBarrier barrier = new CyclicBarrier(10, new StartGame(players));
static {
for (int i=0; i<10; i++) {
Player p = new Player();
players.add(p);
System.out.println("player" + p.id + " 准备进入游戏");
}
}
public static void main(String args[]) {
for (int i=0; i<10; i++)
exec.execute(new LoadGame(players.get(i), barrier));
}
}
class Player {
private static int counter = 1;
private int percentage = 0;
public final int id = counter++;
public void addPercentage(int nextInt) {
percentage += nextInt;
System.out.println("player" + id + " 加载了" + percentage + "%");
}
public int getPercentage() {return percentage;}
}
class LoadGame implements Runnable {
private static Random rand = new Random(47);
private final CyclicBarrier barrier;
private final Player player;
public LoadGame(Player player, CyclicBarrier barrier) {
this.player = player;
this.barrier = barrier;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
if (player.getPercentage() < 96) {
player.addPercentage(rand.nextInt(5) + 1);
} else {
player.addPercentage(100 - player.getPercentage());
}
barrier.await();
}
} catch (InterruptedException e) {
System.out.println();
} catch (BrokenBarrierException e) {
throw new RuntimeException(e);
}
System.out.println("player" + player.id + " 开始游戏");
}
}
class StartGame implements Runnable {
private List<Player> players;
public StartGame(List<Player> players) {
this.players = players;
}
@Override
public void run() {
System.out.println("服务器集中加载一次完毕!");
int i = 0;
for (Player player : players) {
if (player.getPercentage() < 100) {
break;
}
i++;
}
if (i == players.size()) {
System.out.println("比赛开始!");
PlayGame.exec.shutdownNow();
}
}
}
DelayQueue
- 这个是一个延迟队列,他也是线程安全的,存放的泛型类型必须实现Delayed接口。当其实它和优先级队列挺像的,下面是一个例子:
import java.util.*;
import java.util.concurrent.*;
class DelayedTask implements Runnable, Delayed {
private final long delay;
private final long runtime;
private final int id;
public DelayedTask(int id, long delay) {
this.id = id;
this.delay = delay;
this.runtime = System.currentTimeMillis() + delay;
}
@Override
public int compareTo(Delayed o) {
DelayedTask t = (DelayedTask) o;
long result = this.runtime - t.runtime;
if (result > 0) return 1;
else if (result < 0) return -1;
else return 0;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(runtime - System.currentTimeMillis(),
TimeUnit.MILLISECONDS);
}
@Override
public void run() {
System.out.println(id + " run! delay=" + delay);
}
}
class DelayedTaskConsumer implements Runnable {
private DelayQueue<DelayedTask> q;
public DelayedTaskConsumer(DelayQueue<DelayedTask> q) {
this.q = q;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
q.take().run();
}
} catch (InterruptedException e) {}
finally {
System.out.println("finish!");
}
}
}
public class DelayQueueDemo {
public static void main(String[] args) throws Exception {
Random rand = new Random(47);
ExecutorService exec = Executors.newCachedThreadPool();
DelayQueue<DelayedTask> queue = new DelayQueue<DelayedTask>();
for (int i=0; i<20; i++) {
queue.put(new DelayedTask(i + 1, rand.nextInt(5000)));
}
exec.execute(new DelayedTaskConsumer(queue));
Thread.sleep(5000);
exec.shutdownNow();
}
}
PriorityBlockingQueue
- 如果你看过之前集合中的PriorityQueue, 再结合BlockingQueue的用法,我想这个可以省略了。
ScheduledExecutor
- 这是一种定时器的方式,类似于js中的setTimeout()和setInterval()。直接看例子吧。
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ScheduleThreadPoolDemo {
private static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss SSS");
public static void main(String args[]) {
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(5);
exec.schedule(new Mission(), 1000, TimeUnit.MILLISECONDS);
exec.scheduleAtFixedRate(new Mission(), 2000, 1000, TimeUnit.MILLISECONDS);
exec.scheduleWithFixedDelay(new Mission(), 3000, 1000, TimeUnit.MILLISECONDS);
}
static class Mission implements Runnable {
private static int count = 0;
private final int id = ++count;
@Override
public void run() {
System.out.println(id + " run in:" +
sdf.format(new Date(System.currentTimeMillis())));
}
}
}
Semaphore
- 正常的锁(locks或synchronized)在任何时刻都只允许一个任务访问一项资源。而计数信号量允许n个任务同时访问这个资源(这个资源可能是一个对象池)。
import java.lang.reflect.Array;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
private static final int poolsize = 3;
public static void main(String args[]) throws Exception {
Pool<TestObj> pool = new Pool<TestObj>(TestObj.class, poolsize);
ExecutorService exec = Executors.newCachedThreadPool();
for (int i=0; i<poolsize; i++) {
exec.execute(new Hold<TestObj>(pool, (i + 1) * 1000));
}
for (int i=0; i<poolsize; i++) {
exec.execute(new Hold<TestObj>(pool, 500));
}
exec.shutdown();
}
}
class Hold<T> implements Runnable {
private static int count;
private final int id = ++count;
private final Pool<T> pool;
private final long time;
public Hold(Pool<T> pool, long time) {
this.pool = pool;
this.time = time;
}
public void run() {
try {
T task = pool.checkOut();
System.out.println("Thread" + id + " get: " + task);
Thread.sleep(time);
System.out.println("Thread" + id + " release: " + task);
pool.checkIn(task);
System.out.println("Thread" + id + " release success!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class TestObj {
private static int count;
private final int id = ++count;
public int getId() {
return id;
}
public String toString() {
return "resourceId:" + id;
}
}
class Pool<T> {
private Semaphore available;
private int size;
private T[] data;
private boolean[] checkOut;
@SuppressWarnings("unchecked")
public Pool(Class<T> clazz, int size) throws InstantiationException, IllegalAccessException {
available = new Semaphore(size, true);
this.size = size;
checkOut = new boolean[size];
data = (T[]) Array.newInstance(clazz, size);
for (int i=0; i<size; i++) {
data[i] = clazz.newInstance();
}
}
public T checkOut() throws InterruptedException {
available.acquire();
return getItem();
}
public boolean checkIn(T x) throws InterruptedException {
if (releaseItem(x)) {
available.release();
return true;
}
return false;
}
private synchronized T getItem() {
for (int i=0; i<size; i++) {
if (!checkOut[i]) {
checkOut[i] = true;
return (T) data[i];
}
}
return null;
}
private synchronized boolean releaseItem(T x) {
for (int i=0; i<size; i++) {
if (data[i] == x) {
if (checkOut[i]) {
checkOut[i] = false;
return true;
}
return false;
}
}
return false;
}
}
--------------运行结果:
Thread1 get: resourceId:1
Thread2 get: resourceId:2
Thread3 get: resourceId:3
Thread1 release: resourceId:1
Thread1 release success!
Thread4 get: resourceId:1
Thread4 release: resourceId:1
Thread4 release success!
Thread5 get: resourceId:1
Thread2 release: resourceId:2
Thread2 release success!
Thread6 get: resourceId:2
Thread5 release: resourceId:1
Thread5 release success!
Thread6 release: resourceId:2
Thread6 release success!
Thread3 release: resourceId:3
Thread3 release success!
Exchanger
- Exchanger是在两个任务之间交换对象的栅栏。他们各自拥有一个对象,调用exchange()后(可能进入阻塞,等待对方调用这个方法),会得到对方的对象。Exchanger的应用场景是:一个任务在创建对象,这些对象的生产代价很高昂。而另外一个任务在消费这些对象(然后将空容器返回给生产者)。听起来和普通的生产者消费者差不多,区别就是可以在消费这个对象的同时创建新的对象(因代价高昂需尽早创建,且因为调用exchange()会阻塞,也不必担心浪费空间)。可以想象这么一个场景:一共有两个水桶,一个人负责在井边打水,一个人负责拿着装满水的桶去装进自家水库。要是只有一个水桶,打水的和倒水的难免得互相等待。如果有两个桶,倒水的每次只要将空桶交给打水的,然后直接拿走装满水的桶,那么就可以使效率提高。
import java.util.List;
import java.util.concurrent.*;
public class ExchangerDemo {
public static void main(String args[]) {
Exchanger<List<Integer>> changer = new Exchanger<List<Integer>>();
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new ExchangerProducer(changer));
exec.execute(new ExchangerConsumer(changer));
exec.shutdown();
}
}
class ExchangerProducer implements Runnable {
private List<Integer> holder = new CopyOnWriteArrayList<>();
private int begin = 0;
private Exchanger<List<Integer>> changer;
public ExchangerProducer(Exchanger<List<Integer>> changer) {
this.changer = changer;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
for (int i=begin; i<begin+10; i++) {
holder.add(i);
}
begin = begin + 10;
System.out.println("producer 前 " + holder);
holder = changer.exchange(holder);
System.out.println("producer 后 " + holder);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ExchangerConsumer implements Runnable {
private List<Integer> holder = new CopyOnWriteArrayList<>();
private Exchanger<List<Integer>> changer;
public ExchangerConsumer(Exchanger<List<Integer>> changer) {
this.changer = changer;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
System.out.println("consumer 前 " + holder);
holder = changer.exchange(holder);
System.out.println("consumer 后 " + holder);
for (Integer i : holder) {
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
仿真
银行出纳员仿真
- 看这个名字差不多就知道是什么用处,代码有注释。期间遇到了怪异的问题(出队不是最大值),后来看了看以前的文章就明白了。
import java.util.*;
import java.util.concurrent.*;
public class BankTellerSimulation {
private static final int MAX_LINE_SIZE = 50;
private static final int ADJUSTMENT_PERIOD = 1000;
public static void main(String args[]) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool();
CustomerLine customers = new CustomerLine(MAX_LINE_SIZE);
exec.execute(new CustomerGenerator(customers));
exec.execute(new TellerManager(exec, customers, ADJUSTMENT_PERIOD));
System.in.read();
exec.shutdownNow();
}
}
class Customer {
private final int serviceTime;
public Customer(int st) {
serviceTime = st;
}
public int getServiceTime() {
return serviceTime;
}
public String toString() {
return "[" + serviceTime + "]";
}
}
class CustomerLine extends ArrayBlockingQueue<Customer> {
public CustomerLine(int capacity) {
super(capacity);
}
public String toString() {
if (isEmpty()) {
return "[Empty]";
}
StringBuilder result = new StringBuilder();
for (Customer cus : this) {
result.append(cus);
}
return result.toString();
}
}
class CustomerGenerator implements Runnable {
private static Random random = new Random(47);
private CustomerLine customers;
public CustomerGenerator(CustomerLine cl) {
customers = cl;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
Thread.sleep(random.nextInt(300));
customers.put(new Customer(random.nextInt(1000)));
}
} catch (InterruptedException e) {
System.out.println("CustomerGenerator 程序中断");
}
System.out.println("CustomerGenerator 程序停止");
}
}
class Teller implements Runnable, Comparable<Teller>{
private static int counter = 0;
private final int id = counter++;
private int customerServed = 0;
private CustomerLine customers;
private boolean servingCustomerLine = true;
public Teller(CustomerLine cl) {
customers = cl;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
Customer customer = customers.take();
Thread.sleep(customer.getServiceTime());
synchronized (this) {
customerServed++;
while (!servingCustomerLine)
wait();
}
}
} catch (InterruptedException e) {
System.out.println("Teller 程序中断");
}
System.out.println("Teller 程序停止");
}
public synchronized void doSomethingElse() {
servingCustomerLine = false;
}
public synchronized void serveCustomerLine() {
assert !servingCustomerLine : "服务已经在运行!:" + this;
servingCustomerLine = true;
notifyAll();
}
public synchronized int compareTo(Teller o) {
return customerServed - o.customerServed;
}
public String toString() {
return "T" + id + "(" + customerServed + ")";
}
}
class TellerManager implements Runnable {
private ExecutorService exec;
private CustomerLine customers;
private PriorityQueue<Teller> workingTellers = new MyPriorityQueue<Teller>();
private Queue<Teller> tellerDoingOhterThings = new PriorityQueue<Teller>();
private int adjustmentPeriod;
public TellerManager(ExecutorService e,
CustomerLine cl, int adjustmentPeriod) {
exec = e;
customers = cl;
this.adjustmentPeriod = adjustmentPeriod;
newOneTeller();
}
public void adjustTellerNumber() {
if (customers.size() / workingTellers.size() > 2) {
if (tellerDoingOhterThings.size() > 0) {
Teller teller = tellerDoingOhterThings.poll();
teller.serveCustomerLine();
workingTellers.offer(teller);
return;
}
newOneTeller();
return;
}
if (workingTellers.size() > 1 && customers.size() / workingTellers.size() < 2) {
reassingOneTeller();
}
if (customers.size() == 0) {
while (workingTellers.size() > 1) {
reassingOneTeller();
}
}
}
private void newOneTeller() {
Teller teller = new Teller(customers);
exec.execute(teller);
workingTellers.add(teller);
}
private void reassingOneTeller() {
Teller teller = workingTellers.poll();
teller.doSomethingElse();
tellerDoingOhterThings.offer(teller);
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
Thread.sleep(adjustmentPeriod);
adjustTellerNumber();
System.out.print(customers + " {工作中: ");
for (Teller teller : workingTellers) {
System.out.print(teller + " ");
}
System.out.print(", 休息中: ");
for (Teller teller : tellerDoingOhterThings) {
System.out.print(teller + " ");
}
System.out.println("}");
}
} catch (InterruptedException e) {
System.out.println("TellerManager 程序中断");
}
System.out.println("TellerManager 程序结束");
}
}
class MyPriorityQueue<T> extends PriorityQueue<T> {
@Override
public T poll() {
if (isEmpty()) return null;
T[] data = (T[]) toArray();
T max = data[0];
for (int i = 1; i < data.length; i++) {
if (((Comparable<T>) max).compareTo(data[i]) < 0) {
max = data[i];
}
}
remove(max);
return max;
}
}
饭店仿真
import java.util.*;
import java.util.concurrent.*;
public class RestaurantWithQueues {
public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
Restaurant rest = new Restaurant(exec, 5, 2);
exec.execute(rest);
Thread.sleep(10000);
exec.shutdownNow();
}
}
class Order {
private static int counter = 0;
private final int id = counter++;
private final Customer customer;
private final WaitPerson waitPerson;
private final Food food;
public Order(Customer customer, WaitPerson waitPerson, Food food) {
this.customer = customer;
this.waitPerson = waitPerson;
this.food = food;
}
public Food item() {
return food;
}
public Customer getCustomer() {
return customer;
}
public WaitPerson getWaitPerson() {
return waitPerson;
}
public String toString() {
return "Order: " + id + " item: " + food +
" for: " + customer + " served by: " + waitPerson;
}
}
class Plate {
private final Order order;
private final Food food;
public Plate(Order order, Food food) {
this.order = order;
this.food = food;
}
public Order getOrder() {
return order;
}
public Food getFood() {
return food;
}
public String toString() {
return food.toString();
}
}
class Customer implements Runnable {
private static int counter = 0;
private final int id = counter++;
private final WaitPerson waitPerson;
private static Random rand = new Random(47);
private SynchronousQueue<Plate> plateSetting =
new SynchronousQueue<Plate>();
public Customer(WaitPerson wp) {
waitPerson = wp;
}
public void deliver(Plate p) throws InterruptedException {
plateSetting.put(p);
}
@Override
public void run() {
Food[] foods = Food.choose();
System.out.println(this + "下单:" + Arrays.toString(foods));
try {
if (!Thread.interrupted()) {
for (Food food : foods) {
waitPerson.placeOrder(this, food);
System.out.println(this + "eating " + plateSetting.take());
}
}
} catch (InterruptedException e) {
System.out.println(this + "waiting 中断");
}
System.out.println(this + "吃完了");
}
public String toString() {
return "Customer " + id + " ";
}
}
class WaitPerson implements Runnable {
private static int counter = 0;
private final int id = counter++;
private final Restaurant restaurant;
BlockingQueue<Plate> filledOrders =
new LinkedBlockingQueue<Plate>();
public WaitPerson(Restaurant r) {
restaurant = r;
}
public void placeOrder(Customer cust, Food food) {
try {
restaurant.orders.put(new Order(cust, this, food));
} catch (InterruptedException e) {
System.out.println(this + " placeOrder 中断");
}
}
public void run() {
try {
while (!Thread.interrupted()) {
Plate plate = filledOrders.take();
System.out.println(this + "received " + plate
+ " delivering to " + plate.getOrder().getCustomer());
plate.getOrder().getCustomer().deliver(plate);
}
} catch (InterruptedException e) {
System.out.println(this + " 中断");
}
System.out.println(this + " 结束");
}
public String toString() {
return "WaitPerson " + id + " ";
}
}
class Chef implements Runnable {
private static int counter = 0;
private final int id = counter++;
private final Restaurant restaurant;
private static Random rand = new Random(47);
public Chef(Restaurant r) {
restaurant = r;
}
public void run() {
try {
while (!Thread.interrupted()) {
Order order = restaurant.orders.take();
Food item = order.item();
Thread.sleep(rand.nextInt(500));
Plate plate = new Plate(order, item);
order.getWaitPerson().filledOrders.put(plate);
}
} catch (InterruptedException e) {
System.out.println(this + " 中断");
}
System.out.println(this + " 结束");
}
public String toString() {
return "Chef " + id + " ";
}
}
class Restaurant implements Runnable {
private List<WaitPerson> waitPersons = new ArrayList<WaitPerson>();
private List<Chef> chefs = new ArrayList<Chef>();
private ExecutorService exec;
private static Random rand = new Random(47);
BlockingQueue<Order> orders =
new LinkedBlockingQueue<Order>();
public Restaurant(ExecutorService exec, int nWaitPersons, int nChefs) {
this.exec = exec;
for (int i = 0; i < nWaitPersons; i++) {
WaitPerson waiter = new WaitPerson(this);
waitPersons.add(waiter);
exec.execute(waiter);
}
for (int i = 0; i < nChefs; i++) {
Chef chef = new Chef(this);
chefs.add(chef);
exec.execute(chef);
}
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
WaitPerson wp = waitPersons.get(rand.nextInt(waitPersons.size()));
Customer c = new Customer(wp);
exec.execute(c);
Thread.sleep(100);
}
} catch (InterruptedException e) {
System.out.println("Restaurant 中断");
}
System.out.println("Restaurant 结束");
}
}
enum Food {
南汇水蜜桃, 三林糖酱瓜, 佘山兰笋, 松江回鳃鲈, 枫泾西蹄, 城隍庙五香豆, 崇明金瓜, 南桥乳腐, 高桥松饼, 嘉定大白蒜;
private static Random rand = new Random(47);
public static Food[] choose() {
Food[] allfoods = values();
int count = allfoods.length;
for (int i = 0; i < count - 1; i++) {
int index = rand.nextInt(count);
Food temp = allfoods[i];
allfoods[i] = allfoods[index];
allfoods[index] = temp;
}
int need = rand.nextInt(allfoods.length / 2) + 1;
Food[] foods = new Food[need];
int beginIndex = rand.nextInt(count - need + 1);
System.arraycopy(allfoods, beginIndex, foods, 0, need);
return foods;
}
}
分发工作
性能调优
比较各类互斥技术
免锁容器
乐观锁
比较各类Map实现
乐观加锁
ReadWriteLock
活动对象
小结
- 还有这么多的内容,我就不写了。。想开启下一本书,这个就先这样吧。以后想起来了再回来更新。