javase|创建两个线程,其中一个输出1-52,另外一个输出A-Z。输出格式要求(12A 34B 56C 78D 依次类推)

前言 【javase|创建两个线程,其中一个输出1-52,另外一个输出A-Z。输出格式要求(12A 34B 56C 78D 依次类推)】个人观点:线程同步为javaSE中最绕的部分,本文结合内部类,以可重入锁,Synchronized两种方式给大家形象展示了两种风格的迥异之处,该题为线程面试经典题型,希望对即将参加面试广大码农朋友有所帮助!!!

如有错误欢迎再评论区指正;
1 ReentrantLock实现
创建两个线程,其中一个输出1-52,另外一个输出A-Z。输出格式要求:12A 34B 56C 78D 依次类推
提示:定义一个类,其中定义两个方法,第一个方法用于输出数字,方法实现首先使用lock.lock加锁,并输出数字,当输出的数字为偶数时,使用condition.signalAll唤醒其他线程,并使用condition.await让当前线程进入等待队列;第二个方法用于输出字母,方法实现手续使用lock.lock加锁,并输出字母,每输出一个字母,使用condition.signalAll唤醒其他线程,并使用condition.await让当前线程进入等待队列。
注意:方法执行结束后必须使用lock.unlock释放锁标记。condition.await的调用必须有边界判断,避免线程锁死,无法执行。
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Test2 { public static void main(String[] args) { ReentrantLock r1=new ReentrantLock(); //定义一个互斥锁类型 Condition c = r1.newCondition(); //定义一个字母锁条件 Condition c2 = r1.newCondition(); //定义一个数字锁条件 new Thread(new Runnable(){public void run() {try{//逻辑严谨性,定义一个try finally,保证一定释放锁; r1.lock(); //获取锁 for (int i = 1; i <=52; i++) { System.out.println(i+" "); if(i%2==0){ c.signalAll(); //唤醒字母进程 try { c2.await(); //让数字进程等待 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }finally{ r1.unlock(); //释放锁 } }}).start(); new Thread(new Runnable(){ @Override public void run() {try{ r1.lock(); for (int i = 0; i < 26; i++) { System.out.println((char)('A' + i) + " "); c2.signalAll(); try { if(i!=25){//最后一个字母不用进入等待状态 c.await(); }} catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }} }finally{ r1.unlock(); }} }).start(); } }

2 Synchronized锁实现(以下为2019.04.07更新)
创建两个线程,其中一个输出1-52,另外一个输出A-Z。输出格式要求:12A 34B 56C 78D 依次类推。
提示:
定义两个类,分别继承Thread或实现Runnable。其中一个类中的run方法用于输出数字,当输出数字为偶数时wait,进入等待队列,且使用notify唤醒其他线程;另一个类中输出字母,每输出一个字母后,wait进入等待队列,且使用notify唤醒其他线程。两个类的run方法都使用同步代码块,对同一个对象加锁。
public class Problem01 { public static void main(String[] args) { Object object = new Object(); new Thread(new Number(object)).start(); ; new Thread(new Character(object)).start(); ; } } class Number implements Runnable { private Object object; public Number(Object object) { this.object = object; } @Override public void run() { synchronized (object) { for (int i = 1; i < 53; i++) { if (i > 1 && i % 2 == 1) { System.out.print(" "); } System.out.print(i); if (i % 2 == 0) { // 先释放锁,唤醒其他线程,再使本线程阻塞 object.notifyAll(); try { object.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } } class Character implements Runnable { private Object object; public Character(Object object) { this.object = object; } @Override public void run() { synchronized (object) { for (char i = 'A'; i <= 'Z'; i++) { System.out.print(i); // 先释放锁,唤醒其他线程,再使本线程阻塞 object.notifyAll(); if (i < 'Z') {// 线程执行的最后一次不能堵塞,不然会一直堵塞下去。 try { object.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }

    推荐阅读