线程间通信实例之轮流打印ABC

线程间通信,就要联想到Object的wait、notify、notifyAll和Lock.new Condition()的await、signal、signalAll。

【1】需求一,三个线程顺序打印ABC,每个线程打印十次,ABC分别为线程名字

效果如下:

A
A
A
A
A
A
A
A
A
A
//BC依次排列

使用synchronized、wait、notifyAll实例代码如下:

public class TestSwapThread {
    public static void main(String[] args){
		//创建三把锁
        final Object obj1 = new Object();
        final Object obj2 = new Object();
        final Object obj3 = new Object();
        SwapThread swapThread = new SwapThread(obj1,obj2);
        SwapThread swapThread2 = new SwapThread(obj3,obj1);
        SwapThread swapThread3 = new SwapThread(obj2,obj3);
        swapThread.setName("A");
        swapThread.start();
        //这里来保证次序
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        swapThread2.setName("B");
        swapThread2.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        swapThread3.setName("C");
        swapThread3.start();
    }
}

class SwapThread extends  Thread{

    private Object obj1 = null;
    private Object obj2 = null;

    public SwapThread(Object obj1,Object obj2){
        this.obj1 = obj1;
        this.obj2 = obj2;
    }

    @Override
    public void run() {
        synchronized (obj1){
            System.out.println(Thread.currentThread().getName()+"准备进入第二层");
            synchronized (obj2){
                for (int i=0;i<10;i++){
                    System.out.println(Thread.currentThread().getName()+" : "+i);
                }
         //nofityAll并不会释放锁,但是同步代码块执行完会自动释放锁
                obj2.notifyAll();
            }//这里释放内存锁
         //nofityAll并不会释放锁,但是同步代码块执行完会自动释放锁
            obj1.notifyAll();
            System.out.println(Thread.currentThread().getName()+" : end");
        }//这里释放外层锁
    }
}

使用lock实例如下

public class TestSwapThread3 {
    public static void main(String[] args){
    	//这里也可作为swapThread3 构造参数传入
        //Lock lock = new ReentrantLock();
        SwapThread3 swapThread3 = new SwapThread3();
        new Thread(swapThread3,"A").start();
        new Thread(swapThread3,"B").start();
        new Thread(swapThread3,"C").start();

    }
}

class SwapThread3 implements Runnable{
	//共享数据--同一把锁 ReentrantLock
    private Lock lock =new ReentrantLock() ;

    @Override
    public void run() {
	    //加锁
        lock.lock();
        try {
            int count =0;
            while (count<10){
                System.out.println(Thread.currentThread().getName()+" : "+count );
                count++;

            }
        }finally {
	        //释放锁
            lock.unlock();
        }

    }
}

程序执行结果如下:

这里写图片描述

其实lock加锁/释放锁和顺序打印本质是保存线程执行的次序,严格意义从理论来讲,第二种方式在某些情况下是不太正确的。


【2】需求二,三个线程轮流打印ABC,每个线程打印十次,ABC分别为线程名字

效果如下:

A
B
C
//....

这时,就对线程通信要求高了。


使用synchronized、wait、notifyAll实例代码如下:

public class TestSwapThread4 {
    public static void main(String[] args){

        final Object obj1 = new Object();
        final Object obj2 = new Object();
        final Object obj3 = new Object();
        SwapThread4 swapThread = new SwapThread4(obj1,obj2);
        SwapThread4 swapThread2 = new SwapThread4(obj2,obj3);
        SwapThread4 swapThread3 = new SwapThread4(obj3,obj1);
        swapThread.setName("A");
        swapThread.start();

        swapThread2.setName("B");
        swapThread2.start();

        swapThread3.setName("C");
        swapThread3.start();

    }
}

class SwapThread4 extends  Thread{

    private Object obj1 = null;
    private Object obj2 = null;

    public SwapThread4(Object obj1,Object obj2){
        this.obj1 = obj1;
        this.obj2 = obj2;
    }

    @Override
    public void run() {
        for (int i=0;i<10;i++){
            synchronized (obj1){
                synchronized (obj2){
                    System.out.println(Thread.currentThread().getName()+" : "+i);
                    //notifyAll并不会释放锁,代码块结束后释放锁
                    obj2.notifyAll();
                }
                try {
                    //避免程序不能正常结束
                    if (i==9){
                        obj1.notifyAll();
                    }else{
                    //wait方法将会释放锁标志,进入阻塞状态,等到唤醒
                        obj1.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

测试结果如下:

这里写图片描述


使用Lock+Condition实例如下:

public class TestSwapThread2 {

    public static void main(String[] args){
        Lock lock = new ReentrantLock();
        Condition conditionA = lock.newCondition();
        Condition conditionB = lock.newCondition();
        Condition conditionC = lock.newCondition();
        SwapThread2 swapThread = new SwapThread2(lock,conditionA,conditionB);
        SwapThread2 swapThread2 = new SwapThread2(lock,conditionB,conditionC);
        SwapThread2 swapThread3 = new SwapThread2(lock,conditionC,conditionA);

        swapThread.setName("A");
        swapThread.start();

        swapThread2.setName("B");
        swapThread2.start();

        swapThread3.setName("C");
        swapThread3.start();

    }
}

class SwapThread2 extends Thread{

    private Lock lock ;
    private Condition condition1;
    private Condition condition2 ;

    public SwapThread2(Lock lock,Condition condition1,Condition condition2){
        this.lock = lock;
        this.condition1=condition1;
        this.condition2=condition2;
    }


    @Override
    public void run() {
  	  //加锁
        lock.lock();
        try {
            int count =0;
            while (count<10){
            //唤醒等待condition2的线程
                condition2.signal();
                System.out.println(Thread.currentThread().getName()+" : "+count );
                count++;
                if (count==10){
                //避免程序不能结束
                    condition1.signalAll();
                }else{
                    try {
                    	//当前线程进入阻塞,等到condition1被唤醒
                        condition1.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }finally {
            lock.unlock();
        }
    }
}

【3】需求三-如果每次ABC打印次数不一样且要交替进行呢?

实例代码如下:

public class TestABCAlternate {
	
	public static void main(String[] args) {
		AlternateDemo ad = new AlternateDemo();
		//创建线程A,循环20遍loopA
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 1; i <= 20; i++) {
					ad.loopA(i);
				}
			}
		}, "A").start();
		//创建线程B,循环20遍loopB
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 1; i <= 20; i++) {
					ad.loopB(i);
				}
			}
		}, "B").start();
			//创建线程C,循环20遍loopC
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 1; i <= 20; i++) {
					ad.loopC(i);
					System.out.println("-----------------------------------");
				}
			}
		}, "C").start();
	}
}

class AlternateDemo{
	//当前正在执行线程的标记
	private int number = 1; 
	//创建ReentrantLock实例
	private Lock lock = new ReentrantLock();
	//分别创建三个lock的Condition 实例
	private Condition condition1 = lock.newCondition();
	private Condition condition2 = lock.newCondition();
	private Condition condition3 = lock.newCondition();
	
	/**
	 * @param totalLoop : 循环第几轮
	 */
	public void loopA(int totalLoop){
		lock.lock();
		try {
			//1. 判断
			if(number != 1){
			//是当前线程阻塞,等到condition1被唤醒
				condition1.await();
			}
			//2. 打印
			for (int i = 1; i <= 1; i++) {
				System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
			}
			//3. 唤醒
			number = 2;
			condition2.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void loopB(int totalLoop){
		lock.lock();
		try {
			//1. 判断
			if(number != 2){
				condition2.await();
			}
			//2. 打印
			for (int i = 1; i <= 1; i++) {
				System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
			}			
			//3. 唤醒
			number = 3;
			condition3.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void loopC(int totalLoop){
		lock.lock();
		try {
			//1. 判断
			if(number != 3){
				condition3.await();
			}
			//2. 打印一遍
			for (int i = 1; i <= 1; i++) {
				System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
			}
			//3. 唤醒第一个线程 loopA 
			number = 1;
			condition1.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
}

Lock与Condition详解讲解参考博文:Lock与Condition使用讲解

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流烟默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值