线程的对象同步也称为块同步,对象同步锁定的代码执行区域较小,并且能够精确地唤醒所要唤醒的等待线程。所以在使用线程间的通信时应该优先使用对象同步,对象同步比较难以使用。使用不好就回抛出java.lang.IllegalMonitorStateException异常,原因如下:
1.同步的对象必须是线程本身的类变量或者是同步的代码所在的类本身的引用(即this指针)。
2.同步的对象必须是一个对象,而不是一个原子类型对应的对象类型,如Boolean等。
下面给出了两个使用对象同步的经典例子,在实际使用时可以进行扩充,变为实现自己功能的代码.
1.在线程内部使用对象同步
public class ThreadObjectSynchTest {
public static void main(String[] args) {
OperateCompleteFlag u = new OperateCompleteFlag();
MyThread3 t1 = new MyThread3("线程A", u);
MyThread3 t2 = new MyThread3("线程B", u);
MyThread3 t3 = new MyThread3("线程C", u);
MyThread3 t4 = new MyThread3("线程D", u);
MyThread3 t5 = new MyThread3("线程E", u);
MyThread3 t6 = new MyThread3("线程F", u);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
class MyThread3 extends Thread {
private OperateCompleteFlag flag;
MyThread3(String name, OperateCompleteFlag user3) {
super(name);
this.flag = user3;
}
public void run() {
synchronized (flag) {
if (!flag.getIsEnd()) {
try {
flag.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
flag.setIsEnd(false);
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(10L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
synchronized (flag) {
//u.setCash(u.getCash()+y);
System.out.println(Thread.currentThread().getName()
+ "运行结束");
flag.setIsEnd(true);
flag.notify();
}
}
}
class OperateCompleteFlag {
public Boolean getIsEnd() {
return isEnd;
}
public void setIsEnd(Boolean isEnd) {
this.isEnd = isEnd;
}
private Boolean isEnd = true;
}
2.在普通类的方法中使用对象同步
public class ThreadObjectSynchTest2 {
public static void main(String[] args) {
Account u = new Account("张三", 100);
MyThread2 t1 = new MyThread2("线程A", u, 20);
MyThread2 t2 = new MyThread2("线程B", u, -60);
MyThread2 t3 = new MyThread2("线程C", u, -80);
MyThread2 t4 = new MyThread2("线程D", u, -30);
MyThread2 t5 = new MyThread2("线程E", u, 32);
MyThread2 t6 = new MyThread2("线程F", u, 21);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
class MyThread2 extends Thread {
private Account u;
private int y = 0;
MyThread2(String name, Account u, int y) {
super(name);
this.u = u;
this.y = y;
}
public void run() {
u.oper(y);
}
}
class Account {
private String code;
private int cash;
public int getCash() {
return cash;
}
public void setCash(int cash) {
this.cash = cash;
}
public Boolean getIsEnd() {
return isEnd;
}
public void setIsEnd(Boolean isEnd) {
this.isEnd = isEnd;
}
private Boolean isEnd = true;
Account(String code, int cash) {
this.code = code;
this.cash = cash;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
/**
* 业务方法
*
* @param x
* 添加x万元
*/
public void oper(int x) {
try {
synchronized (this) {
if (!isEnd) {
wait();
}
}
isEnd = false;
for (int i = 0; i < 10; i++) {
Thread.sleep(10L);
System.out.println(Thread.currentThread().getName());
}
synchronized (this) {
this.cash += x;
System.out.println(Thread.currentThread().getName()
+ "运行结束,增加“" + x + "”,当前用户账户余额为:" + cash);
isEnd = true;
this.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return "User{" + "code='" + code + '\'' + ", cash=" + cash + '}';
}
}