3、wait()和notify()都是定义在Object类中,其实final的(不能被重写)。两个方法要求被调用时线程已获得对象的锁(在synchronized方法或块中)。当线程执行了wait方法时,该线程会释放掉对象的锁。
代码1:
/**
* 方法声明使用synchronized
* Java中每个对象都有一个锁(lock)或者叫做监视器(monitor),当访问某个对象的synchronized方法时,表示将该对象上锁,当前线程获得该锁。
* 此时其他任何线程都无法再去访问该对象的任何synchronized方法了,直到之前的那个线程执行方法完毕后(或抛出异常),将对象锁释放掉,其他线程才有机会执行。
* (1)synchronized:锁的是方法所在的对象实例
* (2)static synchronized:锁的是方法所在对象所对应的Class对象;java中无论一个类有多少个对象,这些对象会对应唯一一个Class对象。
* 所以当两个线程访问同一个类的两个static synchronized方法时,他们的执行是顺序的(一个先执行完,后一个再执行)
*/
public class Test01 {
public static void main(String[] args) {
Example example = new Example();
Thread t1 = new TestThread1(example);
t1.setName("first thread");
Thread t2 = new TestThread2(example);
t2.setName("second thread");
t1.start();
t2.start();
}
}
class TestThread1 extends Thread {
private Example example;
public TestThread1(Example example) {
this.example = example;
}
@Override
public void run() {
example.execute();
}
}
class TestThread2 extends Thread {
private Example example;
public TestThread2(Example example) {
this.example = example;
}
@Override
public void run() {
example.execute2();
}
}
class Example {
/**
* synchronized:表示该方法的执行需要获得“对象锁(lock)”,当一个线程执行该方法时,会拿到该对象锁。
* 此后,如果其他线程要执行带synchronized的方法(需要获得对象锁的方法),由于锁未释放,所以不能执行。(此时可执行非synchronized的方法)
*/
public synchronized void execute() {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("execute :" + i);
}
}
public synchronized void execute2() {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("execute2 :" + i);
}
}
}
代码2:
/**
* synchronized块(可细粒度的控制)
* 只会将块中的代码同步,位于方法内且synchronized块之外的代码是可以被多个线程执行的
*/
public class Test02 {
public static void main(String[] args) {
Demo example = new Demo();
Thread t3 = new TestThread3(example);
t3.setName("first thread");
Thread t4 = new TestThread4(example);
t4.setName("second thread");
t3.start();
t4.start();
}
}
class TestThread3 extends Thread {
private Demo demo;
public TestThread3(Demo demo) {
this.demo = demo;
}
@Override
public void run() {
demo.execute();
}
}
class TestThread4 extends Thread {
private Demo demo;
public TestThread4(Demo demo) {
this.demo = demo;
}
@Override
public void run() {
demo.execute2();
}
}
class Demo {
private Object object = new Object();
public void execute() {
synchronized (object) { // 锁object对象
// synchronized (this) { // 锁当前对象
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("demo :" + i);
}
}
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("out of synchronized demo :" + i);
}
}
public void execute2() {
synchronized (object) {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("demo2 :" + i);
}
}
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("out of synchronized demo2 :" + i);
}
}
}