创建两个线程,其中一个输出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();
					}
				}
			}
		}
	}
}

你可能感兴趣的:(javase,java,lock,Synchronized)