1、Thread.join()
如果一个线程A的run()
方法中,调用方法B.join()
,那么线程A代码运行到此处时,会等待线程B运行结束后才继续运行。
2、Object.wait()和notify()
一个synchronized
代码块中,
- 如果被共享对象调用
wait()
方法,这个线程就会释放对象锁,进入wait状态(Thread.sleep()
方法不会释放对象锁) - 其他线程可以获取对象锁并运行代码
- 直到在某一个线程内,被共享对象调用
notify()
方法,唤醒wait状态的线程,它们才能继续运行
注意:
调用一次notify()
只能唤醒一个线程,随机选择,如要一次唤醒全部,可调用notifyAll()
方法,被唤醒的所有线程再去竞争对象锁。
3、java.util.concurrent.CountDownLatch
倒计时计数器,适用于一个线程等待其他多个线程全都运行结束后再运行的情况。
CountDownLatch cdl = new CountDownLatch(threadsNumber)
- 其他线程运行完毕后调用
countDown()
方法使计数-1 - 在等待的线程里调用
await()
方法,当计数为0时开始运行
疑惑:
其实我发现在D里依次join A B C其实也可以达到目的啊,并没有出现ABC必须依次运行完毕,D才运行的情况,ABC应该是并行的,为什么说不行呢?
4、java.util.concurrent.CyclicBarrier
CountDownLatch
只能让一个线程await()
,如果我们需要多个线程互相等待对方准备好后,再同时运行的话呢?
比如,一排运动员都站到起点线上,等待所有人准备好后,再同时起跑的情况。
那就需要使用CyclicBarrier
循环栅栏。
CyclicBarrier cb = new CyclicBarrier(threadsNumber)
每个线程各自准备好后,调用CyclicBarrier
对象的await()
方法,所有线程都准备好之后,才同时开始运行。
5、java.util.concurrent.Callable
Runnable
接口的run()
方法是没有返回类型的,假如我们需要子线程返回一个结果给父线程,需要实现Callable
接口。
Callable接口一般与java.util.concurrent.FutureTask
类一起使用,要注意调用FutureTask.get()
方法获取运行结果时,会阻塞主线程。
使用方式
实现Callable<V>
接口,编写call()
方法,返回类型为V
class A implements Callable<Integer>{
@Override
public Integer call() throws Exception{
// 编写任务脚本
}
}
然后把Callable对象作为参数,实例化FutureTask
对象,再把FutureTask
交由Thread驱动
FutureTask futureTask = new FutureTask<Integer>(new A());
new Thread(futureTask).start();
通过FutureTask.get()
方法取得子线程返回的结果,若子线程还没返回结果,会阻塞主线程运行
try {
System.out.println("Before futureTask.get()");
System.out.println("Result:" + futureTask.get());
System.out.println("After futureTask.get()");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}