当前位置: 代码迷 >> 综合 >> 多线程的按序打印
  详细解决方案

多线程的按序打印

热度:99   发布时间:2024-02-05 15:36:01.0

一.首先我们来了解一下Synchroized和Loke的区别

原始构成:
1.Synchroized:属于jvm层面它是java的关键字
底层是monitor对象:
monitorenter(进入)
monitorexit:(出来)

2.synchronized底层是通过monitor对象来完成,其实wait以及notify方法也依赖于monitor对象,只有在同步快或者方法中wait或者notify方法才能被使用。

3.lock是api层面知识是java的一个类。

使用方法:
1.synchronized不需要用户自动释放锁对象,由系统自动退出,有异常和正常两种退出方式。
2.lock则需要用户手动去释放锁对象,如果没有释放所对象的话,就可能会导致死锁问题。需要使用lock和unlock来加锁和
释放锁。

等待是否可以中断:
1.synchronized不可中断,除非抛出异常或者程序的正常的退出。

2.ReentrantLock可以中断:

    设置超时方法tryLock(long timeOut,TimeUnit unit)。

    lockinteruptibly()放入代码块汇总,调用interrupt方法可以中断。


加锁是否公平:
1.synchorized是一个可重入的非公平锁。

2.ReentrantLock两者都是可以的,默认是非公平锁,构造方法可以传入boolean值,true为公平锁,false为非公平锁。

锁绑定多个条件的Condation:

1.ReentrantLock用来实现分组唤醒需要唤醒的线程们,可以精确的唤醒,而不是像synchorized要么随机唤醒唤醒一个要么全部唤醒,synchorized唤醒的方式是要么随机唤醒唤醒一个要么全部唤醒。

基于Lock可以绑定多个Condation以及Condation的精确唤醒,我们可以使用这个属性来进行多线程之间的按序打印相比使用Synchorized方便了许多:

 

题目描述:假设有三个线程ABC,A线程打印五次,接下来B线程打印十次,C线程打印15此,紧接着,A线程打印五次,接下来B线程打印十次,C线程打印15.

代码实现:

package FaceToFace;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;class ShareResource{private int num=1;//num=1表示A线程;num=2表示B线程;num=3表示C线程private Lock lock=new ReentrantLock();private Condition c1=lock.newCondition();private Condition c2=lock.newCondition();private Condition c3=lock.newCondition();public void print5(){lock.lock();try {while (num!=1){c1.await();}for (int i=1;i<=5;i++){System.out.println(Thread.currentThread().getName()+" "+i);}
//通知B线程num=2;c2.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void print10(){lock.lock();try {while (num!=2){c2.await();}for (int i=1;i<=10;i++){System.out.println(Thread.currentThread().getName()+" "+i);}//通知C线程num=3;c3.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void print15(){lock.lock();try {while (num!=3){c3.await();}for (int i=1;i<=15;i++){System.out.println(Thread.currentThread().getName()+" "+i);}//再次唤醒A线程num=1;c1.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}
}
public class SynAndReentranLockDemo {public static void main(String[] args) {ShareResource shareResource = new ShareResource();new Thread(()->{for(int i=1;i<=10;i++){shareResource.print5();}},"A").start();new Thread(()->{for(int i=1;i<=10;i++){shareResource.print10();}},"B").start();new Thread(()->{for(int i=1;i<=10;i++){shareResource.print15();}},"C").start();}}

 

  相关解决方案