Java并发 两个线程交替执行和死锁

今天看到一个题:两个线程交替打印奇数和偶数,即一个线程打印奇数,另一个打印偶数,交替打印从1到100。想了下有多重实现方法。

wait和notify方法:

 1 public class OddEven {
 2 
 3     private static int i = 1;
 4 
 5     private static Object o = new Object();
 6 
 7     private static class MyThread extends Thread {
 8         MyThread(String name) {
 9             super(name);
10         }
11 
12         public void run() {
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 void main(String[] args) {
30         new MyThread("奇 ").start();
31         new MyThread("偶 ").start();
32 
33     }
34 }

---

输出:

奇 1
偶 2
奇 3
偶 4
奇 5
偶 6
奇 7

...

 

LockSupport实现

public class OddEvenLockSupport {

    private static int i = 1;

    private static Thread t1 = new MyThread1();
    private static Thread t2 = new MyThread2();

    public static void main(String[] args) {
        t1.start();
        t2.start();
    }

    private static class MyThread1 extends Thread {
        @Override
        public void run() {
            while (i < 51) {
                System.out.println("奇 " + i++);
                LockSupport.unpark(t2);
                LockSupport.park();
            }
            System.out.println(getName() + " over");
            LockSupport.unpark(t2);
        }

    }

    private static class MyThread2 extends Thread {
        @Override
        public void run() {
            while (i < 51) {
                LockSupport.park();//顺序很重要
                System.out.println("偶 " + i++);
                LockSupport.unpark(t1);
            }
            System.out.println(getName() + " over");
            LockSupport.unpark(t1);
        }

    }
}

 

---

 

使用Condition

public class OddEven2 {

    private static Lock lock = new ReentrantLock();
    static Condition even_c = lock.newCondition();
    static Condition odd_c = lock.newCondition();

    private static class Odd extends Thread {
        public void run() {
            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 extends Thread {
        public void run() {
            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 void main(String[] args) {
        new Even().start();
        new Odd().start();
    }
}

---

 

另一个题,写出会导致死锁的代码:

public class DeadLock extends Thread {
    private Object lock1;
    private Object lock2;

    public DeadLock(Object o1, Object o2) {
        this.lock1 = o1;
        this.lock2 = o2;
    }

    public void run() {
        synchronized (lock1) {
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (lock2) {
                Q.p("end");
            }
        }
    }

    public static void main(String[] args) {
        Object o1 = new Object(), o2 = new Object();
        new DeadLock(o1, o2).start();
        new DeadLock(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

posted @ 2016-12-20 19:11  dahuandahuan  阅读(832)  评论(0编辑  收藏  举报