面试的时候,有一个高频的笔试题:
让2个线程轮流打印,a线程是打印ABCDEFGHIJ,b线程是打印1、2、3、4、5、6、7、8、9、10
这种类型的面试题,主要是考察object的wait()方法和notify()方法的使用
wait()方法用法:
o.wait()会让正在o对象上活动的当前线程进入等待状态,并且释放之前占用的o对象的锁
notify()方法用法:
o.notify()唤醒正在o对象上等待的线程, 只会通知,不会释放之前占用的o对象的锁
2个线程轮流打印,a线程是打印ABCDEFGHIJ,b线程是打印1、2、3、4、5、6、7、8、9、10
- package com.iflytek.sda;
-
- import java.util.Arrays;
- import java.util.List;
-
- public class ThreadTest {
-
- private static final Object lock = new Object();
-
- private static boolean ifPrint = false;
-
- public static void main(String[] args) {
- Thread ta = new Thread(() ->{
- // 要打印的list
- List<String> list = Arrays.asList("A","B","C","D","E","F","G","H","I","J");
- for (int i = 0; i < list.size(); i++){
- synchronized (lock) {
- // 如果ifPrint的值为true,就会进入等待状态
- while (ifPrint) {
- try{
- lock.wait();
- }catch (Exception e){
-
- }
- }
- // 到了这一步,说明ifPrint的值为false,然后就会打印
- System.out.print(list.get(i));
- // 修改ifPrint的值为true,这样再次进入该方法时会进入等待状态,不会进行打印
- ifPrint = true;
- // 唤醒正在lock对象上等待的线程
- lock.notify();
- }
- }
- });
- Thread tb = new Thread(() ->{
- for (int i = 0; i < 10; i++){
- synchronized (lock) {
- // 如果ifPrint的值为false,就会进入等待状态
- while (!ifPrint) {
- try{
- lock.wait();
- }catch (Exception e){
-
- }
- }
- // 到了这一步,说明ifPrint的值为true,然后就会打印
- System.out.print(i+1);
- // 修改ifPrint的值为false,这样再次进入该方法时会进入等待状态,不会进行打印
- ifPrint = false;
- // 唤醒正在lock对象上等待的线程
- lock.notify();
- }
- }
- });
- ta.start();
- tb.start();
- }
- }
一开始,ifPrint为false,此时,ta线程会进行打印,打印A;tb线程会处于等待状态;
等ta打印完毕,修改ifPrint为true,并且唤醒其它等待线程。
此时,ta线程会处于等待状态;tb线程会进行打印,打印1
等tb打印完毕,修改ifPrint为false,并且唤醒其它等待线程。
此时,ta线程会进行打印,打印B;tb线程会处于等待状态;
....
以此类推:

上面是2个线程,可以通过true、false的两种状态来区分,那如果是3个线程呢,4个线程呢,要怎么办?
3个线程,轮流打印,第一个线程只打印A,第二个线程只打印B,第三个线程只打印C
- package com.iflytek.sda;
-
-
- public class ThreadTest2 {
-
- private static Integer flag = 1;
-
- private static final Object lock = new Object();
-
- public static void main(String[] args) {
-
- Thread threadA = new Thread(()->{
- for (int i = 0 ; i < 10; i++){
- synchronized (lock){
- while(flag != 1){
- try{
- lock.wait();
- }catch (Exception e){
-
- }
- }
- System.out.print("A");
- flag = 2;
- lock.notifyAll();
- }
- }
- });
- Thread threadB = new Thread(()->{
- for (int i = 0 ; i < 10; i++){
- synchronized (lock){
- while(flag != 2){
- try{
- lock.wait();
- }catch (Exception e){
-
- }
- }
- System.out.print("B");
- flag = 3;
- lock.notifyAll();
- }
- }
- });
- Thread threadC = new Thread(()->{
- for (int i = 0 ; i < 10; i++){
- synchronized (lock){
- while(flag != 3){
- try{
- lock.wait();
- }catch (Exception e){
-
- }
- }
- System.out.print("C");
- flag = 1;
- lock.notifyAll();
- }
- }
- });
- threadA.start();
- threadB.start();
- threadC.start();
- }
- }
-

这里的代码写在同一个类里面,标志位写在最上面可以共用,实际用法中都不在一个类里面,要怎么办呢?
- package com.example.demo.thread;
-
- public class ThreadPrint {
-
- public static Integer flag = 1;
- public static void main(String[] args) {
-
- Thread ta = new Thread(new ThreadA());
- Thread tb = new Thread(new ThreadB());
- ta.start();
- tb.start();
- }
- }
-
- class ThreadA implements Runnable{
-
- @Override
- public void run() {
- for(int i = 0 ; i < 10; i++){
- synchronized (ThreadPrint.class){
- while (ThreadPrint.flag != 1){
- try {
- ThreadPrint.class.wait();
- }catch (Exception e){
-
- }
- }
- System.out.print("1");
- ThreadPrint.flag = 2;
- ThreadPrint.class.notifyAll();
- }
- }
- }
- }
-
- class ThreadB implements Runnable{
-
- @Override
- public void run() {
- for(int i = 0 ; i < 10; i++){
- synchronized (ThreadPrint.class){
- while (ThreadPrint.flag != 2){
- try {
- ThreadPrint.class.wait();
- }catch (Exception e){
-
- }
- }
- System.out.print("A");
- ThreadPrint.flag = 1;
- ThreadPrint.class.notifyAll();
- }
- }
- }
- }
好几个线程同理,
另外,超过两个线程就需要使用notifyAll,唤醒对象上的所有线程