程序中的所有事物,在任意时刻都只能执行一个步骤.
并发解决的问题大体上可以分为"速度"和"设计可管理性"两种
并发通常是提高运行在单处理器上的程序的性能.
实现并发最直接的方式是在操作系统级别使用进程.
困难: 协调不同线程驱动的任务之间的对内存/IO 资源的使用. 以使得这些资源不会同时被多个任务访问.
Java 的线程机制是抢占式,表示调度机制会周期性的中断线程,将上下文切换到另一个线程,从而为每个线程都提供时间片,使得每个程序都会分配到数量合理的时间去驱动它的任务.
将程序划分为多个分离的/独立运行的任务.通过使用多线程机制,这些独立任务中的每一个都将由执行线程来驱动.
一个线程就是在进程中的一个单一的顺序控制流,因此,单个进程可以拥有多个并发执行的任务.
底层机制是切分 CPU 时间.
线程可以驱动任务,因此你需要一种描述任务的方式,可以由 Runnable 接口来提供.
将 Runnable 对象转换为工作任务的传统方式就是把它交给一个 Thread 构造器.
管理 Thread 对象.
单个 Executor 被用来创建和管理系统中的所有任务
shutdown () 方法的调用可以防止新的任务提交给Executor
Runnable 是执行工作的独立任务,但是它并不返回任何值.
任务完成之时能够返回值: 实现 Callable 接口.
Callabel 是一种具有参数类型的泛型,它的类型参数表示的事从方法 call()中返回值.
并且必须使用 ExecutorService.submit()方法调用它.
submit()方法会产生 Future 对象,他用 Callable 返回结果的特定类型进行了参数化.
用 isDone() 方法,查看任务是否完成.
package com.step21;
import java.util.ArrayList;
import java.util.concurrent.*;
class TaskWithResult implements Callable{
private int id ;
public TaskWithResult(int id){
this.id = id ;
}
@Override
public String call() throws Exception {
return "result of TaskWithResult : "+id + " , currentThread : " + Thread.currentThread().getName();
}
}
public class CallableDemo {
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList> list = new ArrayList<>();
for (int i = 0 ; i<10 ; i++) {
list.add(exec.submit(new TaskWithResult(i))) ;
}
for (Future fs : list) {
System.out.println(fs.get());
}
exec.shutdown();
}
}
output:
result of TaskWithResult : 0 , currentThread : pool-1-thread-1
result of TaskWithResult : 1 , currentThread : pool-1-thread-2
result of TaskWithResult : 2 , currentThread : pool-1-thread-3
result of TaskWithResult : 3 , currentThread : pool-1-thread-3
result of TaskWithResult : 4 , currentThread : pool-1-thread-1
result of TaskWithResult : 5 , currentThread : pool-1-thread-3
result of TaskWithResult : 6 , currentThread : pool-1-thread-3
result of TaskWithResult : 7 , currentThread : pool-1-thread-1
result of TaskWithResult : 8 , currentThread : pool-1-thread-1
result of TaskWithResult : 9 , currentThread : pool-1-thread-3
sleep() 使任务终止执行指定的时间.
线程的优先级是将该线程的重要性传递给了调度器.
尽管 CPU 处理现有线程集的顺序是不确定的,但是调度器将倾向于让优先权最高的线程先执行.
然而,并不意味着优先权较低的线程将得不到执行.
优先级较低的线程仅仅是执行的频率较低.
在绝大多数的时间里,所有线程有应该以默认的优先级运行,试图操纵线程优先级通常是一种错误.
程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序中不可或缺的部分.因此,当所有的非后台线程结束时.程序也就终止了,同时会杀死进程中的所有后台线程. 反过来说,只要有任何非后台线程还在运行,程序就不会终止.
必须在线程启动前调用 setDaemon()方法,才能把它设置为后台线程.
继承 Thread
join() : 等待一段时间,直到第二个线程结束才继续执行.
package com.step21;
class Sleeper extends Thread{
private int duration ;
public Sleeper(String name , int sleepTime){
super(name);
this.duration = sleepTime;
start();
}
public void run (){
try {
sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + "has awakened ... ");
}
}
class Joiner extends Thread{
private Sleeper sleeper ;
public Joiner(String name , Sleeper sleeper){
super(name);
this.sleeper = sleeper;
start();
}
public void run (){
try {
sleeper.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + "join completed ... ");
}
}
public class Joining {
public static void main(String[] args) {
Sleeper sleepy = new Sleeper("Sleepy",1500) ;
Sleeper grumpy = new Sleeper("Sleepy",1500);
Joiner dopey = new Joiner("Dopey",sleepy) ;
Joiner doc = new Joiner("Doc",sleepy) ;
grumpy.interrupt();
}
}
Connected to the target VM, address: '127.0.0.1:55371', transport: 'socket'
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.step21.Sleeper.run(Joining.java:15)
Sleepyhas awakened ...
Sleepyhas awakened ...
Dopeyjoin completed ...
Docjoin completed ...
Disconnected from the target VM, address: '127.0.0.1:55371', transport: 'socket'
创建有响应的用户界面.
线程组持有一个线程集合.
"继续错误的代价由别人承担,承认错误的代价由自己承担"
由于线程的本质特性,使得你不能捕获从线程中逃逸的异常.
package com.step21;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
class ExceptionThread2 implements Runnable {
public void run(){
Thread t = Thread.currentThread();
System.out.println(" run () by " + t);
System.out.println(" eh = "+ t.getUncaughtExceptionHandler());
throw new RuntimeException();
}
}
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("caught : " + e );
}
}
class HandlerThreadFactory implements ThreadFactory{
public Thread newThread(Runnable r){
System.out.println(this+ " create new Thread .. ");
Thread t = new Thread(r) ;
System.out.println(" crreate " + t);
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler() );
System.out.println(" eh = " + t.getUncaughtExceptionHandler() );
return t ;
}
}
public class CaptureUncaughtException {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool(new HandlerThreadFactory());
exec.execute(new ExceptionThread2());
}
}
输出:
Connected to the target VM, address: '127.0.0.1:55756', transport: 'socket'
com.step21.HandlerThreadFactory@546a03af create new Thread ..
crreate Thread[Thread-0,5,main]
eh = com.step21.MyUncaughtExceptionHandler@28864e92
run () by Thread[Thread-0,5,main]
eh = com.step21.MyUncaughtExceptionHandler@28864e92
com.step21.HandlerThreadFactory@546a03af create new Thread ..
crreate Thread[Thread-1,5,main]
eh = com.step21.MyUncaughtExceptionHandler@46d3a9
caught : java.lang.RuntimeException
Disconnected from the target VM, address: '127.0.0.1:55756', transport: 'socket'
这个处理器只有在不存在线程专有的未捕获异常处理器的情况下才会被调用.
系统会检查线程专有版本, 如果没有发现,则检查线程组是否有其专有的 UNcaughtException()方法
如果也没有,在调用 defaultUncaughtExceptionHandler.
方案: 序列化访问共享资源 - 给定时刻只允许一个任务访问共享资源. - 互斥量
synchronized void f(){ /*......*/}
synchronized void g(){ /*......*/}
所有对象都自动含有单一的锁.当在对象上调用其任意 synchronized 方法的时候,次对象都被加锁.这时该对象上的其他 synchronized 方法只有等到前一个方法调用完毕并释放了锁之后才能被调用.
在使用并发时,将域设置为 private 是非常重要的,否则 synchronized 关键字就不能防止其他任务直接访问域,这样就会产生冲突.
读写线程必须用相同的监视器锁同步
每个访问临界共享资源的方法都必须被同步,否则他们就不能正确的工作.
Lock 对象必须被显式地创建.锁定和释放.
Lock() 必须放置在 finally 子句中带有 unlock 的 try-finally 的语句中.
ReentrantLock允许你尝试着获取但最终未获得锁,如果其他人已经获取了锁,那么你就可以决定离开去做其他的事情了.而不是等待直至这个锁被释放.
//: concurrency/AttemptLocking.java
package concurrency; /* Added by Eclipse.py */
// Locks in the concurrent library allow you
// to give up on trying to acquire a lock.
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
public class AttemptLocking {
private ReentrantLock lock = new ReentrantLock();
public void untimed() {
boolean captured = lock.tryLock();
try {
System.out.println("tryLock(): " + captured);
} finally {
if(captured)
lock.unlock();
}
}
public void timed() {
boolean captured = false;
try {
captured = lock.tryLock(2, TimeUnit.SECONDS);
} catch(InterruptedException e) {
throw new RuntimeException(e);
}
try {
System.out.println("tryLock(2, TimeUnit.SECONDS): " + captured);
} finally {
if(captured)
lock.unlock();
}
}
public static void main(String[] args) {
final AttemptLocking al = new AttemptLocking();
al.untimed(); // True -- lock is available
al.timed(); // True -- lock is available
// Now create a separate task to grab the lock:
new Thread() {
{ setDaemon(true); }
public void run() {
al.lock.lock();
System.out.println("acquired");
}
}.start();
Thread.yield(); // Give the 2nd task a chance
al.untimed(); // False -- lock grabbed by task
al.timed(); // False -- lock grabbed by task
}
}
/* Output:
tryLock(): true
tryLock(2, TimeUnit.SECONDS): true
acquired
tryLock(): false
tryLock(2, TimeUnit.SECONDS): false
*///:~
原子操作时不能被线程调度机制中断的操作.
一旦操作开始,那么它一定可以在可能发生的"上下文切换"之前(切换到其他线程)执行完毕.
原子操作可由线程机制保证其不可中断.
AtomicInteger
AtomicLong
AtomicReference
防止多个线程同时访问方法内部的部分代码而不是防止访问整个方法. 通过这总方式分离出的代码段成为临界区.
使用 synchronized 关键字建立.
必须确保所有相关任务都是在同一个对象上同步.
防止任务在共享资源上产生冲突的第二种方式就是根除对变量的共享.
java.lang.ThreadLocal 类实现.
ThreadLocal对象通常当做静态域存储.
//: concurrency/ThreadLocalVariableHolder.java
package concurrency; /* Added by Eclipse.py */
// Automatically giving each thread its own storage.
import java.util.concurrent.*;
import java.util.*;
class Accessor implements Runnable {
private final int id;
public Accessor(int idn) { id = idn; }
public void run() {
while(!Thread.currentThread().isInterrupted()) {
ThreadLocalVariableHolder.increment();
System.out.println(this);
Thread.yield();
}
}
public String toString() {
return "#" + id + ": " +
ThreadLocalVariableHolder.get();
}
}
public class ThreadLocalVariableHolder {
private static ThreadLocal value =
new ThreadLocal() {
private Random rand = new Random(47);
protected synchronized Integer initialValue() {
return rand.nextInt(10000);
}
};
public static void increment() {
value.set(value.get() + 1);
}
public static int get() { return value.get(); }
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++)
exec.execute(new Accessor(i));
TimeUnit.SECONDS.sleep(3); // Run for a while
exec.shutdownNow(); // All Accessors will quit
}
}
/* Output: (Sample)
#0: 9259
#1: 556
#2: 6694
#3: 1862
#4: 962
#0: 9260
#1: 557
#2: 6695
#3: 1863
#4: 963
...
*///:~
//: concurrency/OrnamentalGarden.java
package concurrency; /* Added by Eclipse.py */
import java.util.concurrent.*;
import java.util.*;
import static net.mindview.util.Print.*;
class Count {
private int count = 0;
private Random rand = new Random(47);
// Remove the synchronized keyword to see counting fail:
public synchronized int increment() {
int temp = count;
if(rand.nextBoolean()) // Yield half the time
Thread.yield();
return (count = ++temp);
}
public synchronized int value() { return count; }
}
class Entrance implements Runnable {
private static Count count = new Count();
private static List entrances =
new ArrayList();
private int number = 0;
// Doesn't need synchronization to read:
private final int id;
private static volatile boolean canceled = false;
// Atomic operation on a volatile field:
public static void cancel() { canceled = true; }
public Entrance(int id) {
this.id = id;
// Keep this task in a list. Also prevents
// garbage collection of dead tasks:
entrances.add(this);
}
public void run() {
while(!canceled) {
synchronized(this) {
++number;
}
print(this + " Total: " + count.increment());
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch(InterruptedException e) {
print("sleep interrupted");
}
}
print("Stopping " + this);
}
public synchronized int getValue() { return number; }
public String toString() {
return "Entrance " + id + ": " + getValue();
}
public static int getTotalCount() {
return count.value();
}
public static int sumEntrances() {
int sum = 0;
for(Entrance entrance : entrances)
sum += entrance.getValue();
return sum;
}
}
public class OrnamentalGarden {
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++)
exec.execute(new Entrance(i));
// Run for a while, then stop and collect the data:
TimeUnit.SECONDS.sleep(3);
Entrance.cancel();
exec.shutdown();
if(!exec.awaitTermination(250, TimeUnit.MILLISECONDS))
print("Some tasks were not terminated!");
print("Total: " + Entrance.getTotalCount());
print("Sum of Entrances: " + Entrance.sumEntrances());
}
}
/* Output: (Sample)
Entrance 0: 1 Total: 1
Entrance 2: 1 Total: 3
Entrance 1: 1 Total: 2
Entrance 4: 1 Total: 5
Entrance 3: 1 Total: 4
Entrance 2: 2 Total: 6
Entrance 4: 2 Total: 7
Entrance 0: 2 Total: 8
...
Entrance 3: 29 Total: 143
Entrance 0: 29 Total: 144
Entrance 4: 29 Total: 145
Entrance 2: 30 Total: 147
Entrance 1: 30 Total: 146
Entrance 0: 30 Total: 149
Entrance 3: 30 Total: 148
Entrance 4: 30 Total: 150
Stopping Entrance 2: 30
Stopping Entrance 1: 30
Stopping Entrance 0: 30
Stopping Entrance 3: 30
Stopping Entrance 4: 30
Total: 150
Sum of Entrances: 150
*///:~
线程状态:
进入阻塞状态
1.Runnable.run() 方法的中间打断, 设立标识, 清理资源
2. Thread 类包含 interrupt() 方法.
3. Executor cancel(true)
//: concurrency/Interrupting.java
package concurrency; /* Added by Eclipse.py */
// Interrupting a blocked thread.
import java.util.concurrent.*;
import java.io.*;
import static net.mindview.util.Print.*;
class SleepBlocked implements Runnable {
public void run() {
try {
TimeUnit.SECONDS.sleep(100);
} catch(InterruptedException e) {
print("InterruptedException");
}
print("Exiting SleepBlocked.run()");
}
}
class IOBlocked implements Runnable {
private InputStream in;
public IOBlocked(InputStream is) { in = is; }
public void run() {
try {
print("Waiting for read():");
in.read();
} catch(IOException e) {
if(Thread.currentThread().isInterrupted()) {
print("Interrupted from blocked I/O");
} else {
throw new RuntimeException(e);
}
}
print("Exiting IOBlocked.run()");
}
}
class SynchronizedBlocked implements Runnable {
public synchronized void f() {
while(true) // Never releases lock
Thread.yield();
}
public SynchronizedBlocked() {
new Thread() {
public void run() {
f(); // Lock acquired by this thread
}
}.start();
}
public void run() {
print("Trying to call f()");
f();
print("Exiting SynchronizedBlocked.run()");
}
}
public class Interrupting {
private static ExecutorService exec =
Executors.newCachedThreadPool();
static void test(Runnable r) throws InterruptedException{
Future> f = exec.submit(r);
TimeUnit.MILLISECONDS.sleep(100);
print("Interrupting " + r.getClass().getName());
f.cancel(true); // Interrupts if running
print("Interrupt sent to " + r.getClass().getName());
}
public static void main(String[] args) throws Exception {
test(new SleepBlocked());
test(new IOBlocked(System.in));
test(new SynchronizedBlocked());
TimeUnit.SECONDS.sleep(3);
print("Aborting with System.exit(0)");
System.exit(0); // ... since last 2 interrupts failed
}
}
/* Output: (95% match)
Interrupting SleepBlocked
InterruptedException
Exiting SleepBlocked.run()
Interrupt sent to SleepBlocked
Waiting for read():
Interrupting IOBlocked
Interrupt sent to IOBlocked
Trying to call f()
Interrupting SynchronizedBlocked
Interrupt sent to SynchronizedBlocked
Aborting with System.exit(0)
*///:~
//: concurrency/MultiLock.java
package concurrency; /* Added by Eclipse.py */
// One thread can reacquire the same lock.
import static net.mindview.util.Print.*;
public class MultiLock {
public synchronized void f1(int count) {
if(count-- > 0) {
print("f1() calling f2() with count " + count);
f2(count);
}
}
public synchronized void f2(int count) {
if(count-- > 0) {
print("f2() calling f1() with count " + count);
f1(count);
}
}
public static void main(String[] args) throws Exception {
final MultiLock multiLock = new MultiLock();
new Thread() {
public void run() {
multiLock.f1(10);
}
}.start();
}
}
/* Output:
f1() calling f2() with count 9
f2() calling f1() with count 8
f1() calling f2() with count 7
f2() calling f1() with count 6
f1() calling f2() with count 5
f2() calling f1() with count 4
f1() calling f2() with count 3
f2() calling f1() with count 2
f1() calling f2() with count 1
f2() calling f1() with count 0
*///:~
interrupt()
interrupted()
//: concurrency/InterruptingIdiom.java
package concurrency; /* Added by Eclipse.py */
// General idiom for interrupting a task.
// {Args: 1100}
import java.util.concurrent.*;
import static net.mindview.util.Print.*;
class NeedsCleanup {
private final int id;
public NeedsCleanup(int ident) {
id = ident;
print("NeedsCleanup " + id);
}
public void cleanup() {
print("Cleaning up " + id);
}
}
class Blocked3 implements Runnable {
private volatile double d = 1.0;
public void run() {
try {
while(!Thread.interrupted()) {
// point1
NeedsCleanup n1 = new NeedsCleanup(1);
// Start try-finally immediately after definition
// of n1, to guarantee proper cleanup of n1:
try {
print("Sleeping");
TimeUnit.SECONDS.sleep(1);
// point2
NeedsCleanup n2 = new NeedsCleanup(2);
// Guarantee proper cleanup of n2:
try {
print("Calculating");
// A time-consuming, non-blocking operation:
for(int i = 1; i < 2500000; i++)
d = d + (Math.PI + Math.E) / d;
System.out.println("d: " + d);
print("Finished time-consuming operation");
} finally {
n2.cleanup();
}
} finally {
n1.cleanup();
}
}
print("Exiting via while() test");
} catch(InterruptedException e) {
print("Exiting via InterruptedException");
}
}
}
public class InterruptingIdiom {
public static void main(String[] args) throws Exception {
if(args.length != 1) {
print("usage: java InterruptingIdiom delay-in-mS");
System.exit(1);
}
Thread t = new Thread(new Blocked3());
t.start();
TimeUnit.MILLISECONDS.sleep(new Integer(args[0]));
t.interrupt();
}
}
/* Output: (Sample)
NeedsCleanup 1
Sleeping
NeedsCleanup 2
Calculating
Finished time-consuming operation
Cleaning up 2
Cleaning up 1
NeedsCleanup 1
Sleeping
Cleaning up 1
Exiting via InterruptedException
*///:~
使用线程来同时运行多个任务时,可以通过使用锁(互斥)来同步两个任务的行为.从而使得一个任务不会干涉另一个任务的资源.
wait(): 等待某个条件发生变化,而改变这个条件超出了当前方法的控制能力,释放锁 . 由 notify()或 notifyAll 唤醒.
sheep(): 锁没有释放,yield() 也属于这种情况.
当调用 wait()时,声明:"我已经刚刚做完能做的所有事情,因此我要在这里等待,但是我希望其他的 synchronized 操作在条件合适的情况下能够执行"
对 wait()而言,与 sleep 有所区别.:
1.在 wait()期间,对象锁是释放的.
2.可以通过 notify() 或者 notifyAll() , 或者令时间到期,从 wait()中恢复执行.
调用 wait() , nofify()和 notifyAll()的任务在调用这些方法前,必须"拥有"(获取)对象的锁?.
//: concurrency/waxomatic/WaxOMatic.java
// Basic task cooperation.
package concurrency.waxomatic;
import java.util.concurrent.*;
import static net.mindview.util.Print.*;
class Car {
private boolean waxOn = false;
public synchronized void waxed() {
waxOn = true; // Ready to buff
notifyAll();
}
public synchronized void buffed() {
waxOn = false; // Ready for another coat of wax
notifyAll();
}
public synchronized void waitForWaxing()
throws InterruptedException {
while(waxOn == false)
wait();
}
public synchronized void waitForBuffing()
throws InterruptedException {
while(waxOn == true)
wait();
}
}
class WaxOn implements Runnable {
private Car car;
public WaxOn(Car c) { car = c; }
public void run() {
try {
while(!Thread.interrupted()) {
printnb("抛光 Wax On! ");
TimeUnit.MILLISECONDS.sleep(500);
car.waxed();
car.waitForBuffing();
}
} catch(InterruptedException e) {
print("Exiting via interrupt");
}
print("Ending Wax On task");
}
}
class WaxOff implements Runnable {
private Car car;
public WaxOff(Car c) { car = c; }
public void run() {
try {
while(!Thread.interrupted()) {
car.waitForWaxing();
printnb("打蜡 Wax Off! ");
TimeUnit.MILLISECONDS.sleep(500);
car.buffed();
}
} catch(InterruptedException e) {
print("Exiting via interrupt");
}
print("Ending Wax Off task");
}
}
public class WaxOMatic {
public static void main(String[] args) throws Exception {
Car car = new Car();
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new WaxOff(car));
exec.execute(new WaxOn(car));
TimeUnit.SECONDS.sleep(5); // Run for a while...
exec.shutdownNow(); // Interrupt all tasks
}
}
/* Output: (95% match)
抛光 Wax On!
打蜡 Wax Off!
抛光 Wax On!
打蜡 Wax Off!
抛光 Wax On!
打蜡 Wax Off!
抛光 Wax On!
打蜡 Wax Off!
抛光 Wax On!
打蜡 Wax Off!
Exiting via interrupt
Exiting via interrupt
Ending Wax On task
Ending Wax Off task
*///:~
当 notifyAll()因某个特定锁而被调用时,只有等待的这个锁的任务才被唤醒.
//: concurrency/Restaurant.java
package concurrency; /* Added by Eclipse.py */
// The producer-consumer approach to task cooperation.
import java.util.concurrent.*;
import static net.mindview.util.Print.*;
class Meal {
private final int orderNum;
public Meal(int orderNum) { this.orderNum = orderNum; }
public String toString() { return "Meal " + orderNum; }
}
class WaitPerson implements Runnable {
private Restaurant restaurant;
public WaitPerson(Restaurant r) { restaurant = r; }
public void run() {
try {
while(!Thread.interrupted()) {
synchronized(this) {
while(restaurant.meal == null)
wait(); // ... for the chef to produce a meal
}
print("Waitperson got " + restaurant.meal);
synchronized(restaurant.chef) {
restaurant.meal = null;
restaurant.chef.notifyAll(); // Ready for another
}
}
} catch(InterruptedException e) {
print("WaitPerson interrupted");
}
}
}
class Chef implements Runnable {
private Restaurant restaurant;
private int count = 0;
public Chef(Restaurant r) { restaurant = r; }
public void run() {
try {
while(!Thread.interrupted()) {
synchronized(this) {
while(restaurant.meal != null)
wait(); // ... for the meal to be taken
}
if(++count == 10) {
print("Out of food, closing");
restaurant.exec.shutdownNow();
}
printnb("Order up! ");
synchronized(restaurant.waitPerson) {
restaurant.meal = new Meal(count);
restaurant.waitPerson.notifyAll();
}
TimeUnit.MILLISECONDS.sleep(100);
}
} catch(InterruptedException e) {
print("Chef interrupted");
}
}
}
public class Restaurant {
Meal meal;
ExecutorService exec = Executors.newCachedThreadPool();
WaitPerson waitPerson = new WaitPerson(this);
Chef chef = new Chef(this);
public Restaurant() {
exec.execute(chef);
exec.execute(waitPerson);
}
public static void main(String[] args) {
new Restaurant();
}
}
/* Output:
Order up! Waitperson got Meal 1
Order up! Waitperson got Meal 2
Order up! Waitperson got Meal 3
Order up! Waitperson got Meal 4
Order up! Waitperson got Meal 5
Order up! Waitperson got Meal 6
Order up! Waitperson got Meal 7
Order up! Waitperson got Meal 8
Order up! Waitperson got Meal 9
Out of food, closing
WaitPerson interrupted
Order up! Chef interrupted
*///:~
//: concurrency/waxomatic2/WaxOMatic2.java
// Using Lock and Condition objects.
package concurrency.waxomatic2;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import static net.mindview.util.Print.*;
class Car {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private boolean waxOn = false;
public void waxed() {
lock.lock();
try {
waxOn = true; // Ready to buff
condition.signalAll();
} finally {
lock.unlock();
}
}
public void buffed() {
lock.lock();
try {
waxOn = false; // Ready for another coat of wax
condition.signalAll();
} finally {
lock.unlock();
}
}
public void waitForWaxing() throws InterruptedException {
lock.lock();
try {
while(waxOn == false)
condition.await();
} finally {
lock.unlock();
}
}
public void waitForBuffing() throws InterruptedException{
lock.lock();
try {
while(waxOn == true)
condition.await();
} finally {
lock.unlock();
}
}
}
class WaxOn implements Runnable {
private Car car;
public WaxOn(Car c) { car = c; }
public void run() {
try {
while(!Thread.interrupted()) {
printnb("Wax On! ");
TimeUnit.MILLISECONDS.sleep(500);
car.waxed();
car.waitForBuffing();
}
} catch(InterruptedException e) {
print("Exiting via interrupt");
}
print("Ending Wax On task");
}
}
class WaxOff implements Runnable {
private Car car;
public WaxOff(Car c) { car = c; }
public void run() {
try {
while(!Thread.interrupted()) {
car.waitForWaxing();
printnb("Wax Off! ");
TimeUnit.MILLISECONDS.sleep(500);
car.buffed();
}
} catch(InterruptedException e) {
print("Exiting via interrupt");
}
print("Ending Wax Off task");
}
}
public class WaxOMatic2 {
public static void main(String[] args) throws Exception {
Car car = new Car();
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new WaxOff(car));
exec.execute(new WaxOn(car));
TimeUnit.SECONDS.sleep(3);
exec.shutdownNow();
}
}
/* Output: (90% match)
Wax On!
Wax Off!
Wax On!
Wax Off!
Wax On!
Wax Off!
Exiting via interrupt
Exiting via interrupt
Ending Wax Off task
Ending Wax On task
Disconnected from the target VM, address: '127.0.0.1:58743', transport: 'socket'
*///:~
//: concurrency/ToastOMatic.java
package concurrency; /* Added by Eclipse.py */
// A toaster that uses queues.
import java.util.concurrent.*;
import java.util.*;
import static net.mindview.util.Print.*;
class Toast {
public enum Status { DRY, BUTTERED, JAMMED }
private Status status = Status.DRY;
private final int id;
public Toast(int idn) { id = idn; }
public void butter() { status = Status.BUTTERED; }
public void jam() { status = Status.JAMMED; }
public Status getStatus() { return status; }
public int getId() { return id; }
public String toString() {
return "Toast " + id + ": " + status;
}
}
class ToastQueue extends LinkedBlockingQueue {}
class Toaster implements Runnable {
private ToastQueue toastQueue;
private int count = 0;
private Random rand = new Random(47);
public Toaster(ToastQueue tq) { toastQueue = tq; }
public void run() {
try {
while(!Thread.interrupted()) {
TimeUnit.MILLISECONDS.sleep(
100 + rand.nextInt(500));
// Make toast
Toast t = new Toast(count++);
print(t);
// Insert into queue
toastQueue.put(t);
}
} catch(InterruptedException e) {
print("Toaster interrupted");
}
print("Toaster off");
}
}
// Apply butter to toast:
class Butterer implements Runnable {
private ToastQueue dryQueue, butteredQueue;
public Butterer(ToastQueue dry, ToastQueue buttered) {
dryQueue = dry;
butteredQueue = buttered;
}
public void run() {
try {
while(!Thread.interrupted()) {
// Blocks until next piece of toast is available:
Toast t = dryQueue.take();
t.butter();
print(t);
butteredQueue.put(t);
}
} catch(InterruptedException e) {
print("Butterer interrupted");
}
print("Butterer off");
}
}
// Apply jam to buttered toast:
class Jammer implements Runnable {
private ToastQueue butteredQueue, finishedQueue;
public Jammer(ToastQueue buttered, ToastQueue finished) {
butteredQueue = buttered;
finishedQueue = finished;
}
public void run() {
try {
while(!Thread.interrupted()) {
// Blocks until next piece of toast is available:
Toast t = butteredQueue.take();
t.jam();
print(t);
finishedQueue.put(t);
}
} catch(InterruptedException e) {
print("Jammer interrupted");
}
print("Jammer off");
}
}
// Consume the toast:
class Eater implements Runnable {
private ToastQueue finishedQueue;
private int counter = 0;
public Eater(ToastQueue finished) {
finishedQueue = finished;
}
public void run() {
try {
while(!Thread.interrupted()) {
// Blocks until next piece of toast is available:
Toast t = finishedQueue.take();
// Verify that the toast is coming in order,
// and that all pieces are getting jammed:
if(t.getId() != counter++ ||
t.getStatus() != Toast.Status.JAMMED) {
print(">>>> Error: " + t);
System.exit(1);
} else
print("Chomp! " + t);
}
} catch(InterruptedException e) {
print("Eater interrupted");
}
print("Eater off");
}
}
public class ToastOMatic {
public static void main(String[] args) throws Exception {
ToastQueue dryQueue = new ToastQueue(),
butteredQueue = new ToastQueue(),
finishedQueue = new ToastQueue();
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Toaster(dryQueue));
exec.execute(new Butterer(dryQueue, butteredQueue));
exec.execute(new Jammer(butteredQueue, finishedQueue));
exec.execute(new Eater(finishedQueue));
TimeUnit.SECONDS.sleep(2);
exec.shutdownNow();
}
} /* (Execute to see output) *///:~
//: concurrency/PipedIO.java
package concurrency; /* Added by Eclipse.py */
// Using pipes for inter-task I/O
import java.util.concurrent.*;
import java.io.*;
import java.util.*;
import static net.mindview.util.Print.*;
class Sender implements Runnable {
private Random rand = new Random(47);
private PipedWriter out = new PipedWriter();
public PipedWriter getPipedWriter() { return out; }
public void run() {
try {
while(true)
for(char c = 'A'; c <= 'z'; c++) {
printnb("Sender: " + c + ", ");
out.write(c);
TimeUnit.MILLISECONDS.sleep(rand.nextInt(500));
}
} catch(IOException e) {
print(e + " Sender write exception");
} catch(InterruptedException e) {
print(e + " Sender sleep interrupted");
}
}
}
class Receiver implements Runnable {
private PipedReader in;
public Receiver(Sender sender) throws IOException {
in = new PipedReader(sender.getPipedWriter());
}
public void run() {
try {
while(true) {
// Blocks until characters are there:
printnb("Read: " + (char)in.read() + ", ");
}
} catch(IOException e) {
print(e + " Receiver read exception");
}
}
}
public class PipedIO {
public static void main(String[] args) throws Exception {
Sender sender = new Sender();
Receiver receiver = new Receiver(sender);
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(sender);
exec.execute(receiver);
TimeUnit.SECONDS.sleep(4);
exec.shutdownNow();
}
} /* Output: (65% match)
Read: A, Read: B, Read: C, Read: D, Read: E, Read: F, Read: G, Read: H, Read: I, Read: J, Read: K, Read: L, Read: M, java.lang.InterruptedException: sleep interrupted Sender sleep interrupted
java.io.InterruptedIOException Receiver read exception
*///:~
尚未完成,节后整理.........
680