记一次多线程顺序打印ABC问题学习总结

2018-11-21  本文已影响0人  减肥是不可能减肥的温

方法一:Object.wait()

package demo1;

public class ThreadDemo2 implements Runnable {
    private String lock = new String("lock"); //三个线程共用一个锁
    private volatile int state = 0;

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        try {
            for (int i = 0; i < 10; i++) {
                if (name.equals("A")) {
                    while (state % 3 != 0) {
                        synchronized(lock){
                            lock.wait();}
                    }
                } else if (name.equals("B")) {
                    while (state % 3 != 1) {
                        synchronized(lock){
                            lock.wait();}
                    }

                } else if (name.equals("C")) {
                    while (state % 3 != 2) {
                        synchronized(lock){
                            lock.wait();}
                    }
                }
                System.out.print(name);  //必须在state改变前输出,否则可能导致乱序
                state++;
                synchronized(lock){
                    lock.notifyAll();}
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadDemo2 task = new ThreadDemo2();
        Thread thread1 = new Thread(task,"A");
        Thread thread2 = new Thread(task,"B");
        Thread thread3 = new Thread(task,"C");
        thread1.start();
        thread2.start();
        thread3.start();
    }

}

方法2:Condition.await()

package demo1;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadDemo implements Runnable {

    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    
    private volatile int state = 0;

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        lock.lock();
        //进入临界区
        try {
            for (int i = 0; i < 5; i++) {
                if (name.equals("A")) {
                    while ( state % 3 != 0) {
                        condition.await();//条件不满足,暂时阻塞线程,暂时释放lock
                    }

                } else if (name.equals("B")) {
                    while (state % 3 != 1) {
                        condition.await();
                    }
                } else if (name.equals("C")) {
                    while (state % 3 != 2) {
                        condition.await();
                    }
                }
                System.out.print(name);    //在state改变前输出,否则可能导致乱序
                state++;
                condition.signalAll();//通知正在等待的线程,此时有可能已经满足条件
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();// 记得要释放锁
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadDemo task = new ThreadDemo();
        Thread thread1 = new Thread(task,"A");
        Thread thread2 = new Thread(task,"B");
        Thread thread3 = new Thread(task,"C");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

方法3:公平锁 ReentrantLock

package demo1;

import java.util.concurrent.locks.ReentrantLock;

public class ThreadDemo3 implements Runnable{
    //true表示公平锁,竞争锁的线程依次加入等待队列,先加入队列的先获取锁,关键在于加入等待队列的顺序
    private ReentrantLock lock = new ReentrantLock(true);  
                                                            
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        try {           
            if ("B".equals(name)) {
                Thread.sleep(10);    //确保线程按顺序进入等待队列
            }else if ("C".equals(name)) {
                Thread.sleep(20);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 5; i++) {
            lock.lock();   //获取锁
            try {           
                System.out.print(name);  //获取线程名字
                Thread.sleep(30);   //确保A线程等待BC线程进入队列后再进行后续
            } catch (InterruptedException e) {
                e.printStackTrace();
            }  finally {
                lock.unlock();   //释放锁
            }
        }
    }
    
    public static void main(String[] args) {
        ThreadDemo3 task = new ThreadDemo3();
        Thread thread1 = new Thread(task,"A");
        Thread thread2 = new Thread(task,"B");
        Thread thread3 = new Thread(task,"C");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}
上一篇 下一篇

猜你喜欢

热点阅读