要实现多个线程执行完成先后,就要知道如何实现线程之间的等待,java线程等待实现是join。java的jdk中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;
}
}
}

实现需求的方案一:

 public class TestMain {
public static void main(String[] args) throws InterruptedException {
Thread T1 = new MyThread("T1");
Thread T2 = new MyThread("T2");
Thread T3 = new MyThread("T3"); System.out.println("T1 start.");
T1.start();
T1.join();
System.out.println("T1 complete."); System.out.println("T2 start.");
T2.start();
T2.join();
System.out.println("T2 complete."); System.out.println("T3 start.");
T3.start();
T3.join();
System.out.println("T3 complete.");
}
} class MyThread extends Thread {
public MyThread(String name) {
setName(name);
} @Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
try {
// do something...
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

实现需求的方案二:

public class Test2Main {
public static void main(String[] args) {
final Thread T1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("T1...");
}
});
final Thread T2 = new Thread(new Runnable() {
@Override
public void run() {
try {
T1.join();
}catch (InterruptedException ex){
ex.printStackTrace();
}
System.out.println("T2...");
}
});
final Thread T3 = new Thread(new Runnable() {
@Override
public void run() {
try {
T2.join();
}catch (InterruptedException ex){
ex.printStackTrace();
}
System.out.println("T3...");
}
}); T3.start();
T2.start();
T1.start();
}
}

实现方案三:使用ReentrantLock来解决, 还有个state整数用来判断轮到谁执行了

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class ABC {
private static Lock lock = new ReentrantLock();//通过JDK5中的锁来保证线程的访问的互斥
private static int state = 0; static class ThreadA extends Thread {
@Override
public void run() {
for (int i = 0; i < 10;) {
lock.lock();
if (state % 3 == 0) {
System.out.print("A");
state++;
i++;
}
lock.unlock();
}
}
} static class ThreadB extends Thread {
@Override
public void run() {
for (int i = 0; i < 10;) {
lock.lock();
if (state % 3 == 1) {
System.out.print("B");
state++;
i++;
}
lock.unlock();
}
}
} static class ThreadC extends Thread {
@Override
public void run() {
for (int i = 0; i < 10;) {
lock.lock();
if (state % 3 == 2) {
System.out.print("C");
state++;
i++;
}
lock.unlock();
}
}
} public static void main(String[] args) {
new ThreadA().start();
new ThreadB().start();
new ThreadC().start();
} }

使用lock来保证只有一个线程在输出操作, 要保证了state不会被两个线程同时修改, 思路简单

实现方案四:还可以使用condition, condition的效率可能会更高一些, await会释放lock锁, condition的await和signal与object的wait和notify方法作用类似

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class ABC2 {
private static Lock lock = new ReentrantLock();
private static int count = 0;
private static Condition A = lock.newCondition();
private static Condition B = lock.newCondition();
private static Condition C = lock.newCondition(); static class ThreadA extends Thread { @Override
public void run() {
lock.lock();
try {
for (int i = 0; i < 10; i++) {
while (count % 3 != 0)
A.await(); // 会释放lock锁
System.out.print("A");
count++;
B.signal(); // 唤醒相应线程
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} } static class ThreadB extends Thread { @Override
public void run() {
lock.lock();
try {
for (int i = 0; i < 10; i++) {
while (count % 3 != 1)
B.await();
System.out.print("B");
count++;
C.signal();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} } static class ThreadC extends Thread { @Override
public void run() {
lock.lock();
try {
for (int i = 0; i < 10; i++) {
while (count % 3 != 2)
C.await();
System.out.println("C");
count++;
A.signal();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} } public static void main(String[] args) throws InterruptedException {
new ThreadA().start();
new ThreadB().start();
ThreadC threadC = new ThreadC();
threadC.start();
threadC.join();
System.out.println(count);
}
}

实现方案五:使用信号量也可以, 这个思路最简单, 整个代码也比较简洁

import java.util.concurrent.Semaphore;

public class ABC3 {
private static Semaphore A = new Semaphore(1);
private static Semaphore B = new Semaphore(1);
private static Semaphore C = new Semaphore(1); static class ThreadA extends Thread { @Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
A.acquire();
System.out.print("A");
B.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} } static class ThreadB extends Thread { @Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
B.acquire();
System.out.print("B");
C.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} } static class ThreadC extends Thread { @Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
C.acquire();
System.out.println("C");
A.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} } public static void main(String[] args) throws InterruptedException {
B.acquire(); C.acquire(); // 开始只有A可以获取, BC都不可以获取, 保证了A最先执行
new ThreadA().start();
new ThreadB().start();
new ThreadC().start();
}
}

注意:

lock是需要lock所有者去释放的, 即谁lock, 谁释放, 不可以跨线程, 会报java.lang.IllegalMonitorStateException;

semaphore是没有所有者的说法, 可以跨线程释放和获取.

方案三、四、五转自《[Java多线程]ABC三个线程顺序输出的问题

Java-JUC(零):Java:现有线程T1/T2/T3,如何确保T1执行完成之后执行T2,T3在T2执行完成之后执行。的更多相关文章

  1. Java:现有线程T1/T2/T3,如何确保T1执行完成之后执行T2,T3在T2执行完成之后执行。

    要实现多个线程执行完成先后,就要知道如何实现线程之间的等待,java线程等待实现是join.java的jdk中join方法实现如下: public final synchronized void jo ...

  2. Java - "JUC线程池" 线程状态与拒绝策略源码分析

    Java多线程系列--“JUC线程池”04之 线程池原理(三) 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基本概念"中,我们介绍过,线程有5种状态:新建 ...

  3. Java中的进程与线程(总结篇)

    详细文档: Java中的进程与线程.rar 474KB 1/7/2017 6:21:15 PM 概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进 ...

  4. java 22 - 18 多线程之 线程的状态转换、线程组

    线程的状态转换图解:图片 线程的线程组: 线程组: 把多个线程组合到一起.    它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制. 首先创建一个Runnable的实现类 publi ...

  5. java多线程编程(二创建线程)

    1.概念           因为java是完全面向对象的,所以在java中,我们说的线程,就是Thread类的一个实例对象.所以,一个线程就是一个对象,它有自己字段和方法. 2.创建线程 创建线程有 ...

  6. 黑马程序员——JAVA基础之多线程的线程间通讯等

    ------- android培训.java培训.期待与您交流! ---------- 线程间通讯: 其实就是多个线程在操作同一个资源,但是动作不同. wait(); 在其他线程调用此对象的notif ...

  7. java多线程总结五:线程池的原理及实现

    1.线程池简介:     多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.        假设一个服务器完成一项任务所需时间为:T1 创 ...

  8. JAVA技术专题综述之线程篇(1)

    本文详细介绍JAVA技术专题综述之线程篇 编写具有多线程能力的程序经常会用到的方法有: run(),start(),wait(),notify(),notifyAll(),sleep(),yield( ...

  9. Java多线程(十)——线程优先级和守护线程

    一.线程优先级的介绍 java 中的线程优先级的范围是1-10,默认的优先级是5.“高优先级线程”会优先于“低优先级线程”执行. java 中有两种线程:用户线程和守护线程.可以通过isDaemon( ...

随机推荐

  1. IO模型之AIO代码及其实践详解

    一.AIO简介 AIO是java中IO模型的一种,作为NIO的改进和增强随JDK1.7版本更新被集成在JDK的nio包中,因此AIO也被称作是NIO2.0.区别于传统的BIO(Blocking IO, ...

  2. 偶然发现的几个OPENWRT工具安装包

    https://rychly.gitlab.io/openwrt-packages/ 有心人已经打好包了,下载拿用 例如:dropbrute https://rychly.gitlab.io/open ...

  3. 1.利用BeanMap进行对象与Map的相互转换

    javabean与map的转换有很多种方式,比如: 1.通过ObjectMapper先将bean转换为json,再将json转换为map,但是这种方法比较绕,且效率很低,经测试,循环转换10000个b ...

  4. Oracle前期工具【1】

    目录: 1.oracle下载安装[Oracle11g] 2.Oracle客户端工具下载安装 [sqldeveloper.exe] 3.cmd进入Oracle命令界面操作 4.客户端图形化命令操作 or ...

  5. Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释

     原题链接   无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点:然后再把所有点遍历一遍 ...

  6. Vue、webpack中默认的config.js、index.js 配置详情

    在vue.js 框架搭建好后,其vue-cli 自动构建的目录里面相关环境变量及其基本变量配置,如下代码所示: module.exports = { build: { index: path.reso ...

  7. TCP三次握手,四次回收的每一步的解释

    三次握手 第一次握手:主机A发送位码为syn=1,随机产生seq number=10001的数据包到服务器,主机B由SYN=1知道,A要求建立联机,此时状态为SYN_SENT: 第二次握手:主机B收到 ...

  8. Prometheus+Grafana监控

    什么是Prometheus? Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB).Prometheus使用Go语言开发,是Google BorgMon监控系统 ...

  9. 多任务创建-线程(IO密集型适用)

    单核CPU:时间片轮转 并行:CPU的个数大于等于任务数 真的多任务执行 并发:CPU的个数小于任务数 假的多任务 知识点: 多线程共享全局变量 创建线程的两种方法: 1.创建子线程方法 调用函数 T ...

  10. 2019 杭电多校第八场 HDU - 6665 Calabash and Landlord 两矩形分平面

    题意 给出两个矩形,问这两个矩形把平面分成了几部分. 分析 不需要什么高级技能,只需 “简单” 的分类讨论. (实在太难写了,对拍找出错误都不想改 推荐博客,其中有个很好的思路,即只讨论答案为2,3, ...