大数据,机器学习,人工智能大数据 爬虫Python AI Sql大数据

多线程之间的协调(一):线程等待其它线程

2019-02-14  本文已影响0人  b91cbec6a902

如何让线程A等待线程B执行完以后再往下执行?

1、使用Object类的wait()和notifyAll()方法。

示意代码:

public class MyRunner implements Runnable {
    private Object lock;

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

    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread线程执行完了~");
        synchronized (lock) {
            lock.notifyAll();
        }
    }
}
@Test
public void test_0() throws InterruptedException {
    Object lock = new Object();

    Thread thread = new Thread(new MyRunner2(lock));
    thread.start();

    synchronized (lock) {
        lock.wait();
    }
    System.out.println("主线程执行完了~");
}

运行结果:

thread线程执行完了~
主线程执行完了~

注意:wait()方法一定要在notifyAll()之前执行,否则线程会错失此次被唤醒的机会,然后一直等待下去。

示意代码:

@Test
public void test_0() throws InterruptedException {
    Object lock = new Object();

    Thread thread = new Thread(new MyRunner(lock));
    thread.start();

    Thread.sleep(2000);

    synchronized (lock) {
        lock.wait();
    }
    System.out.println("主线程执行完了~");
}

运行结果:

thread线程执行完了~
// 主线程一直处于等待中

2、使用Thread类的wait()方法。

线程结束时会自动唤醒等待在当前Thread对象上的所有线程。

示意代码:

@Test
public void test_1() throws InterruptedException {
    Thread thread = new Thread(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread线程执行完了~");
    });
    thread.start();
    
    synchronized (thread) {
        thread.wait();
    }
    System.out.println("主线程执行完了~");
}

运行结果:

thread线程执行完了~
主线程执行完了~

注意:wait()方法一定要在thread线程运行结束之前执行,否则主线程会错失此次被唤醒的机会,然后一直等待下去。

示意代码:

@Test
public void test_1() throws InterruptedException {
    Thread thread = new Thread(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread线程执行完了~");
    });
    thread.start();

    Thread.sleep(2000)

    synchronized (thread) {
        thread.wait();
    }
    System.out.println("主线程执行完了~");
}

运行结果:

thread线程执行完了~
// 主线程一直处于等待中

3、使用Thread类的join()方法。

示意代码:

@Test
public void test_2() throws InterruptedException {
    Thread thread = new Thread(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread线程执行完了~");
    });
    thread.start();
    
    thread.join();
    System.out.println("主线程执行完了~");
}

运行结果:

thread线程执行完了~
主线程执行完了~

注意:使用join()方法不会出现前两种方法中主线程一直等待的情况。

示意代码:

@Test
public void test_2() throws InterruptedException {
    Thread thread = new Thread(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread线程执行完了~");
    });
    thread.start();
    
    Thread.sleep(2000);
    
    thread.join();
    System.out.println("主线程执行完了~");
}

运行结果:

thread线程执行完了~
主线程执行完了~

join()方法解析:

public final void join() throws InterruptedException {
    join(0);
}

// 先获取Thread对象的锁
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) {
        // 判断该Thread对象是否运行结束,如果运行结束,则不等待。
        // 从这里可以看出,当Thread对象运行结束后再调用Thread对象的join()方法,不会产生任何影响。
        while (isAlive()) {
            // 调用该Thread对象的wait方法
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

从源码可以看出,Thread的join()方法是对Thread的wait()方法的包装,多了一步校验线程是否运行结束的操作。

4、使用CountDownLatch类。

实例代码:

public class MyRunner implements Runnable {
    private CountDownLatch latch;

    public MyRunner(CountDownLatch latch) {
        this.latch = latch;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("thread执行完了~");
        latch.countDown();
    }
}
@Test
public void test_3() throws InterruptedException {
    CountDownLatch latch = new CountDownLatch(1);

    Thread thread = new Thread(new MyRunner(latch));
    thread.start();

    latch.await();
    System.out.println("主线程执行完了~");
}

运行结果:

thread线程执行完了~
主线程执行完了~

如何让线程A等待多个线程执行完以后再往下执行?

使用CountDownLatch类。

示意代码:

@Test
public void test_4() throws InterruptedException {
    CountDownLatch latch = new CountDownLatch(2);

    Thread thread_1 = new Thread(new MyRunner(latch));
    thread_1.start();

    Thread thread_2 = new Thread(new MyRunner(latch));
    thread_2.start();

    latch.await();
    System.out.println("主线程执行完了~");
}

运行结果:

thread线程执行完了~
thread线程执行完了~
主线程执行完了~
上一篇 下一篇

猜你喜欢

热点阅读