CubbyHole Example
The class CubbyHole (see Listing 8.9) simulates a cubbyhole. A cubbyhole is a slot that can have only one item in it at a time. One thread puts an item into the slot and another thread takes it out. If a thread tries to put an item into a cubbyhole that is already occupied, the thread blocks until the slot is available. If a thread tries to remove an item from an empty cubbyhole, the thread blocks until an item is added. In this example, the slot is a reference to an object. This technique allows objects to be handed off from one thread to another in a thread-safe manner.
CubbyHole是指一个通道,某一时刻只能容纳一个东西,一个线程放,另一个线程取。如果已经有东西,不能再放,直到东西被取出。如果没有东西,则不能取,直到放进去新东西。下面给出一个线程安全的解决方案:
CubbyHole.java
/*
* Created on 2005-7-14
*
* Java Thread Programming - Paul Hyde
* Copyright ? 1999 Sams Publishing
* Jonathan Q. Bo 学习笔记
*
*/
package org.tju.msnrl.jonathan.thread.chapter8;
/**
* @author Jonathan Q. Bo from TJU MSNRL
*
* Email:jonathan.q.bo@gmail.com
* Blog:blog.csdn.net/jonathan_q_bo
* blog.yesky.net/jonathanundersun
*
* Enjoy Life with Sun!
*
*/
public class CubbyHole {
private Object obj;
public CubbyHole() {
obj = null;
}
public synchronized void putIn(Object obj) throws InterruptedException{
print("putIn() ... begin");
while(this.obj != null){//等待,直到数据被取出
print("putIn() wait ... begin");
wait();
print("putIn() wait ... end");
}
this.obj = obj;//添加新对象
notifyAll();//通知其它线程:有对象可取
print("putIn() ... end");
}
public synchronized Object takeOut()throws InterruptedException{
print("takeOut() ... begin");
while(obj == null){//等待,直到有数据可以取
print("takeOut() wait ... begin");
wait();
print("takeOut() wait ... end");
}
Object temp = obj;
obj = null;//将原数据清空
notifyAll();//通知其它线程:数据已取出,可填新数据
print("takeOut() ... end");
return temp;
}
public void print(String msg){
String temp = Thread.currentThread().getName();
System.out.println(temp + " - " + msg);
}
}
CubbyHoleMain.java
/*
* Created on 2005-7-14
*
* Java Thread Programming - Paul Hyde
* Copyright ? 1999 Sams Publishing
* Jonathan Q. Bo 学习笔记
*
*/
package org.tju.msnrl.jonathan.thread.chapter8;
/**
* @author Jonathan Q. Bo from TJU MSNRL
*
* Email:jonathan.q.bo@gmail.com
* Blog:blog.csdn.net/jonathan_q_bo
* blog.yesky.net/jonathanundersun
*
* Enjoy Life with Sun!
*
*/
public class CubbyHoleMain {
public static void print(String msg){
String temp = Thread.currentThread().getName();
System.out.println(temp + " - " + msg);
}
public static void main(String[] args) {
final CubbyHole ch = new CubbyHole();
Runnable runA = new Runnable(){
public void run(){
try{
Thread.sleep(500);//故意晚一些执行,让其它线程先取数据
String str;
str="multithreads";
ch.putIn(str);//可一直存
print("run() putIn() " + str);
str = "programming";
ch.putIn(str);
print("run() putIn() " + str);
str = "with java";
ch.putIn(str);
print("run() putIn() " + str);
}catch(InterruptedException e){
print("exception " + e.getMessage());
}
}
};
Runnable runB = new Runnable(){
public void run(){
try{
Object obj;
obj = ch.takeOut();
print("run() takeOut() " + obj);
Thread.sleep(500);//先取,后存
obj = ch.takeOut();//可一直取
print("run() takeOut() " + obj);
obj = ch.takeOut();
print("run() takeOut() " + obj);
}catch(InterruptedException e){
print("exception " + e.getMessage());
}
}
};
Thread threadA = new Thread(runA,"threadA");
threadA.start();
Thread threadB = new Thread(runB,"threadB");
threadB.start();
}
}
输出结果:
threadB - takeOut() ... begin
threadB - takeOut() wait ... begin
threadA - putIn() ... begin
threadA - putIn() ... end
threadB - takeOut() wait ... end
threadB - takeOut() ... end
threadB - run() takeOut() multithreads
threadA - run() putIn() multithreads
threadA - putIn() ... begin
threadA - putIn() ... end
threadA - run() putIn() programming
threadA - putIn() ... begin
threadA - putIn() wait ... begin
threadB - takeOut() ... begin
threadB - takeOut() ... end
threadB - run() takeOut() programming
threadB - takeOut() ... begin
threadB - takeOut() wait ... begin
threadA - putIn() wait ... end
threadA - putIn() ... end
threadA - run() putIn() with java
threadB - takeOut() wait ... end
threadB - takeOut() ... end
threadB - run() takeOut() with java
Using join() to Wait for a Thread to Die
The join() method of Thread can be used to cause the current thread to block waiting for the specified thread to die. This is a relatively crude form of inter-thread communication, but on occasion it can be useful. If threadX runs the code
join()方法使当前线程阻塞,直到指定的线程死亡。
try {
threadY.join()
} catch ( InterruptedException x ) {
}
threadX will block waiting for threadY to die. If threadX is interrupted while inside join(), it will throw an InterruptedException. There are three versions of the join() method available in Thread, all of which are public: join(), join(long), and join(long, int). Additionally, none of these methods can be overridden in a subclass because they are all declared final.
在Thread类中,提供了三个函数:join(),join(long),join(long,int),都被声明为final,不可被子类override
join()
public final void join()
throws InterruptedException
The join() method causes the current thread to block and wait an unlimited amount of time for this thread to die. The current thread will throw an InterruptedException if interrupted while waiting for the specified thread to die.
join()阻塞当前线程直至其死亡,如果等待时被interrupted,会抛出InterruptedException
join(long)
public final synchronized void join(long msTimeout)
throws InterruptedException,
IllegalArgumentException // RuntimeException
The join(long) method causes the current thread to block and wait up to msTimeout milliseconds for the specified thread to die. If msTimeout is 0, the current thread will never time out and will wait forever for the specified thread to die (just like join()). If msTimeout is less than 0, an IllegalArgumentException is thrown. The current thread will throw an InterruptedException if interrupted while waiting for the specified thread to die.
join(long)使当前线程阻塞一定时间(毫秒)等待其死亡,如果设定时间为0,则无限等待不会超时,如果参数小于0,会抛出IllegalArgumentException异常
join(long, int)
精确到纳秒,一般虚拟机未实现此方法
JoinDemo
/*
* Created on 2005-7-14
*
* Java Thread Programming - Paul Hyde
* Copyright ? 1999 Sams Publishing
* Jonathan Q. Bo 学习笔记
*
*/
package org.tju.msnrl.jonathan.thread.chapter8;
/**
* @author Jonathan Q. Bo from TJU MSNRL
*
* Email:jonathan.q.bo@gmail.com
* Blog:blog.csdn.net/jonathan_q_bo
* blog.yesky.net/jonathanundersun
*
* Enjoy Life with Sun!
*
*/
public class JoinDemo {
/**
* 生成一个线程
* @param name 线程名
* @param napTime 线程存活时间
* @return 返回新生成的线程
*/
public static Thread launch(String name, long napTime){
final long sleepTime = napTime;
Runnable run = new Runnable(){
public void run(){
try{
print("run() ... begin");
Thread.sleep(sleepTime);
}catch(InterruptedException e){
print("interrupted");
}finally{
print("run() ... end");
}
}
};
Thread thread = new Thread(run,name);
thread.start();//开始执行
return thread;
}
public static void print(String msg){
String temp = Thread.currentThread().getName();
System.out.println(temp + " - " + msg);
}
public static void main(String[] args) {
Thread[] t = new Thread[3];
t[0] = launch("threadA",2000);
t[1] = launch("threadB",1000);
t[2] = launch("threadC",3000);
for(int i = 0; i < t.length; i++){
try{
String index = "t[" + i + "]";
String name = t[i].getName();
print(name + " is alive ? " + t[i].isAlive());
print(name + " begin join");
long startTime = System.currentTimeMillis();
t[i].join();
long endTime = System.currentTimeMillis();
print(name + " end join, costs " + (endTime - startTime) + "ms");
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
输出结果:
main - threadA is alive ? true
main - threadA begin join
threadA - run() ... begin
threadB - run() ... begin
threadC - run() ... begin
threadB - run() ... end
threadA - run() ... end
main - threadA end join, costs 2000ms
main - threadB is alive ? false
main - threadB begin join
main - threadB end join, costs 0ms
main - threadC is alive ? true
main - threadC begin join
threadC - run() ... end
main - threadC end join, costs 1000ms