zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    POJ3783Balls[DP 最坏情况最优解]
    openjudge2989糖果[DP 01背包可行性]
    POJ1160 Post Office[序列DP]
    石子合并[DP-N3]
    POJ1065Wooden Sticks[DP LIS]
    POJ3636Nested Dolls[DP LIS]
    LCIS(最长公共上升子序列)Vijos1264神秘的咒语
    Vijos1680距离/openjudge2988计算字符串的距离[DP]
    Vijos1392拼拼图的小衫[背包DP|二维信息DP]
    NOIP2000方格取数[DP]
  • 原文地址:https://www.cnblogs.com/luangeng/p/6203991.html
Copyright © 2011-2022 走看看