java.util.concurrent包中有许多涉及多线程并发的工具,使用这些现成工具可以大大简化编码,并且安全高效。
Exchanger提供了一个同步点,即调用exchange方法,当两个线程都到达这个同步点时,两个线程交换数据。
比如,有两个人,一个人需要买一本书,另一个人当然卖一本书,这两个人约定在某地交易,但这两个人距离约定地不同,到达目的地的时间也不同,先到的必须等待直到另一个人到达完成交易。
使用Exchanger类可以很容易实现!
import java.util.*;
import java.util.concurrent.*;
interface Exchangable {
}
class Money implements Exchangable {
private int value;
public Money(int value) {
this.value = value;
}
public String toString() {
return "$" + value;
}
}
class Book implements Exchangable {
private int value;
private String name;
public Book(String name, int value) {
this.name = name;
this.value = value;
}
public String toString() {
String format = "Book: %s($%d)";
return String.format(format, name, value);
}
}
class Seller implements Runnable {
Exchanger<Exchangable> exchanger;
Exchangable book;
public Seller(Exchanger<Exchangable> exchanger) {
this.exchanger = exchanger;
this.book = new Book("Love Java", 88);
}
public void run() {
try {
Random random = new Random(System.currentTimeMillis());
int seconds = random.nextInt(10) + 1;
System.out.println("Hi, I am Seller, I am going to sell a book,waiting " + seconds + "s");
TimeUnit.SECONDS.sleep(seconds);
System.out.println("Hi, I am Seller, I get " + exchanger.exchange(book));
} catch (Exception e) {
}
}
}
class Buyer implements Runnable {
Exchanger<Exchangable> exchanger;
Exchangable money;
public Buyer(Exchanger<Exchangable> exchanger) {
this.exchanger = exchanger;
this.money = new Money(88);
}
public void run() {
try {
Random random = new Random(System.currentTimeMillis() + 99);
int seconds = random.nextInt(10) + 1;
System.out.println("Hi, I am Buyer, I am going to buy a book,waiting " + seconds + "s");
TimeUnit.SECONDS.sleep(seconds);
System.out.println("Hi, I am Buyer, I get " + exchanger.exchange(money));
} catch (Exception e) {
}
}
}
public class ExchangerDemo {
public static void main(String[] args) {
Exchanger<Exchangable> exchanger = new Exchanger<>();
Seller seller = new Seller(exchanger);
Buyer buyer = new Buyer(exchanger);
new Thread(seller).start();
new Thread(buyer).start();
}
}
Exchanger类使用很简单,只有两个public方法,一个是exchange(V x)方法,死等待直到完成交易,另一个是exchange(V x, long time, TimeUnit timeunit),其中x是要交换的数据,time是时间,timeunit指定时间单位,合起来表示最长等待时间,比如exchange(x, 5, TimeUnit.SECONDS)表示最长等待5秒!
ubuntu13.10或以下版本也可以编译,只是源中maven和protobuf都版本太低,需要自己下源码重新编译安装,很繁琐。
hadoop2.5有编译好的发布包,但是默认是64位的,老是出现以下错误
OpenJDK Server VM warning: You have loaded library /hadoop/lib/native/libhadoop.so.1.0.0 which might have disabled stack guard. The VM will try to fix the stack guard now. It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'. 14/08/19 21:07:42 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
看起来好像只是警告无所谓,但在启动脚本中NAMENODES=$(hdfs getconf -namenodes),这时会把所有以上输出以空格作为分隔符作为namenode,显然出错,而且没法加载本地库,所以必须进行重新build。
网上很多说修改HADOOP_OPTS可以解决以上问题,但我试过很多次,根本不行,其实想想也是不可能的,64位的库怎么可以运行在32位呢!
从官方http://www.apache.org/dyn/closer.cgi/hadoop/core/下载源码。
源码是使用maven进行管理的,要求版本必须是maven3以上,由于maven调用了ant,因此ant也是必要的。
另外本地库使用c写的,还要求有cmake,make,auto工具,否则无法编译。总结以下是必要的包: