1.

创建两个线程,一个线程打印1---25
一个线程打印A-Z
输出效果是12A34B56C......5152Z

第一版不符合我们的要求(因为无法确定哪个线程先执行):

public class MyTest {
    public static void main(String[] args) {
        // 创建两个线程,一个线程打印 1---52
        //一个线程打印 A-Z
        //输出效果是 12A34B56C.......5152Z
        //第一版不是很符合我们的要求
        MyObject obj = new MyObject();
        NumberRunnable numberRunnable = new NumberRunnable(obj);
        CharRunnable charRunnable = new CharRunnable(obj);
        Thread th1 = new Thread(numberRunnable);
        Thread th2 = new Thread(charRunnable);

        th1.start();
        th2.start();

    }
}
/*
*
    在某个线程方法中对wait()和notify()的调用必须指定一个Object对象,而且该线程必须拥有该Object对象的monitor。
    而获取对象monitor最简单的办法就是,在对象上使用synchronized关键字。
    当调用wait()方法以后,该线程会释放掉对象锁,并进入sleep状态。
    而在其它线程调用notify()方法时,必须使用同一个Object对象,notify()方法调用成功后,所在这个对象上的相应的等侍线程将被唤醒。
对于被一个对象锁定的多个方法,在调用notify()方法时将会任选其中一个进行唤醒,而notifyAll()则是将其所有等待线程唤醒。
*
* notify()需要在同步方法或同步块中调用,即在调用前,线程必须获得该对象的对象级别锁
在调用wait()方法之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait方法。
*
* */
class MyObject{

}
class NumberRunnable implements Runnable{
    private MyObject obj;
    public NumberRunnable(MyObject obj) {
        this.obj = obj;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 52; i++) {
            synchronized (obj){
                System.out.println(i); //1 2
                if(i%2==0){
                    obj.notify(); //唤醒等待的线程
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }

        }
    }
}
class CharRunnable implements Runnable{

    private MyObject obj;

    public CharRunnable(MyObject obj) {

        this.obj = obj;
    }

    @Override
    public void run() {
        for (int i ='A'; i <='Z'; i++) {
            synchronized (obj){
                System.out.println((char) i);
                obj.notify();
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

定义一个类型作为标记:

public class MyTest {
    public static void main(String[] args) {
        // 创建两个线程,一个线程打印 1---52
        //一个线程打印 A-Z
        //输出效果是 12A34B56C.......5152Z
        MyObject obj = new MyObject();
        NumberRunnable numberRunnable = new NumberRunnable(obj);
        CharRunnable charRunnable = new CharRunnable(obj);
        Thread th1 = new Thread(numberRunnable);
        Thread th2 = new Thread(charRunnable);
        th2.start();
        th1.start();


    }
}

/*
*
    在某个线程方法中对wait()和notify()的调用必须指定一个Object对象,而且该线程必须拥有该Object对象的monitor。
    而获取对象monitor最简单的办法就是,在对象上使用synchronized关键字。
    当调用wait()方法以后,该线程会释放掉对象锁,并进入sleep状态。
    而在其它线程调用notify()方法时,必须使用同一个Object对象,notify()方法调用成功后,所在这个对象上的相应的等侍线程将被唤醒。
对于被一个对象锁定的多个方法,在调用notify()方法时将会任选其中一个进行唤醒,而notifyAll()则是将其所有等待线程唤醒。
*
* notify()需要在同步方法或同步块中调用,即在调用前,线程必须获得该对象的对象级别锁
在调用wait()方法之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait方法。
*
* */

class MyObject{
    // boolean  flag;
   public int flag=1; //int 类型作为标记,可以多标记一下情况
}

class NumberRunnable implements Runnable{

    private MyObject obj;

    public NumberRunnable(MyObject obj) {

        this.obj = obj;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 52; i++) {
            synchronized (obj){
                if(obj.flag!=1){ //1!=1 false
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //开始打印
                System.out.println(i);
                if(i%2==0){
                    obj.flag=2;
                    obj.notify(); //唤醒等待的线程
                }

            }

        }
    }
}

class CharRunnable implements Runnable{

    private MyObject obj;

    public CharRunnable(MyObject obj) {

        this.obj = obj;
    }

    @Override
    public void run() {
        for (int i ='A'; i <='Z'; i++) {
            synchronized (obj){
                if(obj.flag!=2){ //1!=2 true
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println((char) i);
                //修改标记
                obj.flag=1;
                //唤醒等待的线程
                obj.notify();
            }
        }
    }
}

2.

两个线程,一个线程打印100个A,一个线程打印100个B
效果就是 AB AB AB AB......

public class MyTest {
    public static void main(String[] args) {
        //两个线程 一个线程打印100个A 1个线程打印 100个B
        //效果就是AB AB AB AB...
        MyObject obj = new MyObject();
        AThread th1 = new AThread(obj);
        BThread th2 = new BThread(obj);
        th2.start();
        th1.start();
        
    }
}

class MyObject {
    // boolean  flag;
    public int flag = 1; //int 类型作为标记,可以多标记一下情况
}

class AThread extends Thread {
    private MyObject obj;
    public AThread(MyObject obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (obj) {
                if (obj.flag != 1) {
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("A");
                obj.flag = 2;
                obj.notify();
            }
        }
    }
}

class BThread extends Thread {
    private MyObject obj;
    public BThread(MyObject obj) {
        this.obj = obj;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (obj) {
                if (obj.flag != 2) {
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("B");
                obj.flag = 1;
                obj.notify();
            }

        }
    }
}

3.

三个线程 一个线程打印100个A 1个线程打印 100个B  1个线程打印 100个C
效果:ABCABCABCABC

public class MyTest {
    public static void main(String[] args) {

        /*
         *  创建三个线程:一个线程打印 100个A,一个线程打印 100 个 B ,一个线程打印 100个C
         *  输出效果:ABC ABC ABC.....交替打印
         * */
        MyObject obj = new MyObject();
        AThread th1 = new AThread(obj);
        BThread th2 = new BThread(obj);
        CThread th3 = new CThread(obj);
        th1.start();
        th3.start();
        th2.start();


    }
}

class MyObject {
    static int flag = 1;
}

class AThread extends Thread {
    private MyObject obj;

    public AThread(MyObject obj) {
        this.obj = obj;
    }

    @Override
    public void run() {

        for (int i = 0; i < 100; i++) {
            synchronized (obj) {
                //使用while来判断,而不使用if防止虚假唤醒
                while (obj.flag != 1) {
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("A");
                obj.flag = 2;
                // Thread.sleep(1000); 可以等1秒再唤醒对方
                obj.notifyAll(); //唤醒所有等待的线程。
            }
        }

    }
}

class BThread extends Thread {
    private MyObject obj;

    public BThread(MyObject obj) {
        this.obj = obj;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (obj) {
                while (obj.flag != 2) {
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("B");
                obj.flag = 3;
                obj.notifyAll();//唤醒所有等待的线程。
            }
        }
    }
}

class CThread extends Thread {
    private MyObject obj;

    public CThread(MyObject obj) {
        this.obj = obj;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (obj) {
                while (obj.flag != 3) {
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("C");
                obj.flag = 1;
                obj.notifyAll();//唤醒所有等待的线程。
            }
        }
    }
}

把if改成while防止线程假唤醒或伪唤醒:

android打印当前线程是否为主线程_java