2 基本线程同步
2.1使用 synchronized关键字
这一节中,我们将呈现许多秘诀,这个秘诀教会我们如何使用Java语言提供我们的两个基本同步(synchronization)机制:
关键字同步;
锁接口和它的实现。
如果你知道一个方法不会被超过一个线程调用,不用使用synchronized
关键字。你能够使用synchronized方法来递归调用,仅仅一个线程能够访问对象的同步块代码(代码块或者方法)。通常情况下,你将使用这个关键字去引用那个能够执行这个方法的指定对象。
当你使用synchrozied关键字去保护一个代码块时,你使用一个对象作为参数。Java虚拟机保证了仅仅一个线程能够访问这个对象保护的代码块(注意到,我们讨论时对象,不是类)。这个比使用synchronized修饰一个一个方法效率高很多。
下面,我们将看一个简单的例子。
定义一个IPad类,实现基本销售业务。
public class IPad {
private longipad1Number;
private longipad2Number;
public IPad(){
ipad1Number = 200;
ipad2Number = 200;
}
public longgetIpad1Number(){
return ipad1Number;
}
public longgetIpad2Number(){
return ipad2Number;
}
/**
* Sells the ipad 1 with the specifiednumber
* @param number
* @return
*/
public synchronizedbooleansellIpad1(intnumber){
if(number <= ipad1Number){
ipad1Number -= number;
return true;
}
return false;
}
/**
* Sells the ipad 2 with the specifiednumber
* @param number
* @return
*/
public synchronizedbooleansellIpad2(intnumber){
if(number <= ipad2Number){
ipad2Number -= number;
return true;
}
return false;
}
/**
* Returns the number of ipad 1.
* @param number
* @return true
*/
public synchronizedbooleanreturnIpad2(intnumber){
ipad2Number += number;
return true;
}
/**
* Returns the number of ipad 2.
* @param number
* @return true
*/
public synchronizedbooleanreturnIpad1(intnumber){
ipad1Number += number;
return true;
}
}
定义IPadShop1类,销售IPad1和IPad2
public class IPadShop1 implements Runnable {
private IPad ipad;
public IPadShop1(IPad ipad){
this.ipad = ipad;
}
/**
* Core method of this IPad office shop 1.Simulates selling and returning ipad number
*/
@Override
public voidrun() {
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(15));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(196));//false
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(19));
System.out.println("Selling ipad1 15 number is "+ipad.returnIpad1(1));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(150));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(96));//false
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(3));
System.out.println("Selling ipad1 15 number is "+ipad.returnIpad2(3));
}
}
定义IPadShop1类,销售IPad1和IPad2。
public class IPadShop2 implements Runnable {
private IPad ipad;
public IPadShop2(IPad ipad){
this.ipad = ipad;
}
/**
* Core method of this IPad office shop 2.Simulates selling and returning ipad number
*/
@Override
public voidrun() {
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(23));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(16));//false
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(19));
System.out.println("Selling ipad1 15 number is "+ipad.returnIpad1(1));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(50));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(96));//false
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(13));
System.out.println("Selling ipad1 15 number is "+ipad.returnIpad2(3));
}
}
定义测试类SellingIPad类,实现如下:
public class SellingIPad {
/**
* @param args
*/
public staticvoidmain(String[] args) {
IPad ipad = new IPad();
IPadShop1 shop1 = new IPadShop1(ipad);
Thread t1 = new Thread(shop1, "office shop 1");
IPadShop2 shop2 = new IPadShop2(ipad);
Thread t2 = new Thread(shop2, "office shop 2");
t1.start();
t2.start();
try {
// Waits for the finalization of the threads
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" The number of ipad 1 is : "+ ipad.getIpad1Number());
System.out.println(" The number of ipad 2 is : "+ ipad.getIpad2Number());
}
}
运行结果(注意,每次运行的结果可能不同):
Sellingipad1 15 number is true Sellingipad1 15 number is true Sellingipad1 15 number is true Sellingipad1 15 numbe