Java 关于线程的一些使用

版权声明:本文为博主原创文章,转载请注明出处:http://blog.csdn.net/w18756901575 https://blog.csdn.net/w18756901575/article/details/80648902

public class Demo {

    public static void main(String[] agr) throws Exception {
        Demo demo = new Demo();
        demo.test();
    }


    //线程的wait,notify必须和synchronized一起使用
    //即,当前线程拿属于object的锁之后,就可以调用wait让此线程进入等待状态,然后抛出锁,等待其他线程那到object的锁之后唤醒
    //挂在object上的线程,如果有多个线程挂在object一个对象上那么notify只会唤醒一个线程
    public Object object = new Object();

    public void test() throws InterruptedException {

        new Thread() {
            @Override
            public void run() {
                synchronized (object) {
                    L.d("线程1进入等待状态");
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    L.d("线程1继续运行");
                }
            }
        }.start();

        new Thread() {
            @Override
            public void run() {
                synchronized (object) {
                    L.d("线程2进入等待状态");
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    L.d("线程2继续运行");
                }
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                synchronized (object) {
                    L.d("线程3进入等待状态");
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    L.d("线程3继续运行");
                }
            }
        }.start();

        Thread.sleep(1000);
        synchronized (object) {
            object.notify();
        }
    }

}

如果像下面这个没有拿到锁就调起wait就会抛出IllegalMonitorStateException异常

        new Thread() {
            @Override
            public void run() {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

或者是这样,虽然拿到了object的锁但是并没有挂起在object这个对象上就也会抛出异常

        new Thread() {
            @Override
            public void run() {
                synchronized (object){
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
        }.start();

上面两种直接调用的wait是将自己直接挂在Thread本类这个对象上所以要进行拿到本类对象的锁才可以,像下面这样就不会抛出异常

    public void test() throws InterruptedException {
        Thread thread = new Thread() {
            @Override
            public synchronized void run() {
                L.d("线程开始");
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                L.d("线程完成等待");
            }
        };

        thread.start();

        Thread.sleep(1000);
        synchronized (thread) {
            thread.notify();
        }
    }

有关线程的状态

NEW 刚刚创建的线程尚且没有运行
RUNNABLE 正在运行中的线程
WAITING 线程等待中
TIMED_WAITING 计时等待,调用wait(long timeout)之后所处的状态
BLOCKED 阻塞状态,synchronized的锁已经被其他线程拿到而没有释放,此时线程被阻塞在synchronized
TERMINATED 终止状态,线程运行完成

另外如果线程调用sleep是不会释放已经拿到的synchronized锁,如果是调用wait方法则会释放已经到的synchronized锁

关于thread.join()方法的使用,如果在a线程中调用了b线程的join方法,那么a线程就会进入等待直至b线程执行完成才会继续执行,用网上的专业一点的说法就是将线程由并行转为串行,join内部调用的就是wait方法,

例子:

    public void test() {
        Thread thread1 = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    L.d("线程1 : " + i);
                }
            }
        };
        thread1.start();

        Thread thread2 = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    L.d("线程2 : " + i);
                    try {
                        if (i == 5) {
                            thread1.join();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        thread2.start();
    }

join方法的源码:

    public final synchronized void join(long millis) throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/w18756901575/article/details/80648902