notify和wait

题目:启动三个线程,使他们有序的交替的打印0-100java

最开始我想到的是bash

import java.util.concurrent.atomic.AtomicInteger;

public class ThreadTest3 implements Runnable {

    private static final AtomicInteger atomicInteger = new AtomicInteger(0);
    private int i = 0;

    public static void main(String[] args) {
        ThreadTest3 t = new ThreadTest3();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        Thread t3 = new Thread(t);
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t1.start();
        t2.start();
        t3.start();
    }


    @Override
    public void run() {
        while (true){
            if(atomicInteger.get() <100){
                System.out.println(Thread.currentThread().getName() + "_" + atomicInteger.getAndIncrement());
            }else {
                    break;
                }
        }
    }
}
复制代码

结果出来的是ide

t1_0
t1_2
t1_3
t1_4
t1_5
t2_1
t2_7
t1_6
t1_9
t1_10
t1_11
t1_12
t1_13
t1_14
t1_15
t1_16
t1_17
t1_18
t2_8
......
复制代码

一看就是既没有交替有没有有序ui

交替的话,须要一个线程执行完成以后,放弃cpu的资源,想到的就是wait方法,执行wait以前须要执行notify把其余的线程先唤醒this

因而就有了第二个版本atom

public class ThreadTest7 extends Thread {

    private Object lock;
    private static int i;

    public ThreadTest7(Object lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                notify();
                if (i < 100) {
                    System.out.println(Thread.currentThread().getName() + "_" + i);
                    i++;
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else {
                    break;
                }
            }

        }
    }

    public static void main(String[] args) {
        Object lock = new Object();
        Thread t1 = new ThreadTest7(lock);
        Thread t2 = new ThreadTest7(lock);
        Thread t3 = new ThreadTest7(lock);
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t1.start();
        t2.start();
        t3.start();
    }
}

复制代码

输出结果为:交替是交替了,可是没有打完spa

t1_0
t2_1
t3_2
没有而后了
复制代码

查了网上的资料,线程

public class ThreadTest4 implements Runnable{

    int i = 1;

    public static void main(String[] args) {
        ThreadTest4 t = new ThreadTest4();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);

        t1.setName("线程1");
        t2.setName("线程2");

        t1.start();t2.start();
    }

    public void run() {
        while (true) {
            synchronized (this) {
                // 先唤醒另一个线程
                notify();
                if (i <= 100) {
                    System.out.println(this.getClass().getName() + "_" +  this.hashCode());
                    System.out.println(Thread.currentThread().getName() + ":"+ i);
                    i++;
                    try {
                        // 打印完以后,释放资源,等待下次被唤醒
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else {
                    break;
                }
            }
        }
    }

}
复制代码

结果果真能够交替有序的把数字打印出来了。code

Runnable和Thread建立线程的区别
Runnable r = new Runnable();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1和t2会共享到r中的属性,好比上例中的i,以及this也是同一个Runnable t.资源

notify、notifyAll 和 wait

这三个方法都是Object的方法,

方法 注释
notify Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened
notifyAll Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the {@code wait} methods.
wait Causes the current thread to wait until another thread invokes the {@link java.lang.Object#notify()} method or the{@link java.lang.Object#notifyAll()} method for this object.

notify和notifyAll起做用的前提是,他们须要获取同一个object实例的monitor(synchronized的实现原理,synchronized修饰的代码块编译完了以后,实际上是monitorenter和monitorexit两个指令包的,要否则没法唤醒其余的线程,就像个人ThreadTest7。

因此这三个方法必须放在同步代码块中,当线程执行wait()时,会把当前的锁释放,而后让出CPU,进入等待状态。

按照上面的概念,因此若是要使用Thread不用Runnable的话,可使用下面的方式

public class ThreadTest6 extends Thread {

    private static Object lock = new Object();

    private static int i;


    @Override
    public void run() {
        while (true) {

            synchronized (lock) {
                lock.notify();
                if (i < 100) {
                    System.out.println(Thread.currentThread().getName() + "_" + i);
                    i++;
                }
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }

    public static void main(String[] args) {
        Thread t1 = new ThreadTest6();
        Thread t2 = new ThreadTest6();
        Thread t3 = new ThreadTest6();
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t1.start();
        t2.start();
        t3.start();
    }
}

复制代码
相关文章
相关标签/搜索