今天看到一个题:两个线程交替打印奇数和偶数,即一个线程打印奇数,另一个打印偶数,交替打印从1到100。想了下有多重实现方法。
wait和notify方法:
1 public classOddEven {2
3 private static int i = 1;4
5 private static Object o = newObject();6
7 private static class MyThread extendsThread {8 MyThread(String name) {9 super(name);10 }11
12 public voidrun() {13 try{14 synchronized(o) {15 while (i < 100) {16 System.out.println(this.getName() + i++);17 o.notify();18 o.wait();19 }20 o.notify();21 }22 System.out.println(this.getName() + " over");23 } catch(Exception e) {24 e.printStackTrace();25 }26 }27 }28
29 public static voidmain(String[] args) {30 new MyThread("奇 ").start();31 new MyThread("偶 ").start();32
33 }34 }
---
输出:
奇 1
偶 2
奇 3
偶 4
奇 5
偶 6
奇 7
...
LockSupport实现
public classOddEvenLockSupport {private static int i = 1;private static Thread t1 = newMyThread1();private static Thread t2 = newMyThread2();public static voidmain(String[] args) {
t1.start();
t2.start();
}private static class MyThread1 extendsThread {
@Overridepublic voidrun() {while (i < 51) {
System.out.println("奇 " + i++);
LockSupport.unpark(t2);
LockSupport.park();
}
System.out.println(getName()+ " over");
LockSupport.unpark(t2);
}
}private static class MyThread2 extendsThread {
@Overridepublic voidrun() {while (i < 51) {
LockSupport.park();//顺序很重要
System.out.println("偶 " + i++);
LockSupport.unpark(t1);
}
System.out.println(getName()+ " over");
LockSupport.unpark(t1);
}
}
}
---
使用Condition
public classOddEven2 {private static Lock lock = newReentrantLock();static Condition even_c =lock.newCondition();static Condition odd_c =lock.newCondition();private static class Odd extendsThread {public voidrun() {int odd = 1;try{
lock.lock();while (odd < 100) {
System.out.println("奇 " +odd);
odd+= 2;
even_c.signal();
odd_c.await();
}
System.out.println("奇 over");
}catch(InterruptedException e) {
e.printStackTrace();
}finally{
even_c.signal();
lock.unlock();
}
}
}private static class Even extendsThread {public voidrun() {int even = 0;try{
lock.lock();while (even < 100) {
System.out.println("偶 " +even);
even+= 2;
odd_c.signal();
even_c.await();
}
System.out.println("偶 over");
}catch(InterruptedException e) {
e.printStackTrace();
}finally{
odd_c.signal();
lock.unlock();
}
}
}public static voidmain(String[] args) {newEven().start();newOdd().start();
}
}
---
另一个题,写出会导致死锁的代码:
public class DeadLock extendsThread {privateObject lock1;privateObject lock2;publicDeadLock(Object o1, Object o2) {this.lock1 =o1;this.lock2 =o2;
}public voidrun() {synchronized(lock1) {try{
TimeUnit.MILLISECONDS.sleep(500);
}catch(InterruptedException e) {
e.printStackTrace();
}synchronized(lock2) {
Q.p("end");
}
}
}public static voidmain(String[] args) {
Object o1= new Object(), o2 = newObject();newDeadLock(o1, o2).start();newDeadLock(o2, o1).start();
Q.p("main end");
}
}
---
基础回顾:
每个Java对象都拥有一个锁标记,即monitor(监视器),称为对象锁。
wait:
调用obj.wait()方法会阻塞当前线程,直到另一线程调用obj.notify()或obj.notifyAll()方法,其中obj为同一对象,当前线程必须持有obj对象锁,即必须在synchronized方法或代码块中,否则抛出IllegalMonitorStateException。调用wait方法的线程会释放对象锁。
notify:
唤醒一个正在等待该对象锁的线程,若有多个线程都在等待也只会唤醒一个。被唤醒的线程无法立即执行,直到当前线程放弃该对象锁,然后被唤醒的线程会像往常一样与任何其他线程竞争该对象锁,
该方法也必须在持有该对象锁的线程里调用,即必须在synchronized方法或代码块中,否则抛出IllegalMonitorStateException。
synchronized:
synchronized关键字标记一个方法或者代码块,当某个线程调用该对象的synchronized方法或者访问synchronized代码块时,这个线程便获得了该对象的锁,其他线程暂时无法访问这个方法,只有等待这个方法执行完毕或者代码块执行完毕,这个线程才会释放该对象的锁,其他线程才能执行这个方法或者代码块。
end