前言 【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();
}
}
}
}
}
}
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- jvm|【JVM】JVM08(java内存模型解析[JMM])
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)