要实现多个线程执行完成先后,就要知道如何实现线程之间的等待,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. Powershell-常用脚本

    function Test-Port { Param([string]$ComputerName,$port = 5985,$timeout = 1000) try { $tcpclient = Ne ...

  2. CEIWEI CommMonitor 串口监控精灵v11.0 串口过滤 串口监控

    CEIWEI CommMonitor   串行端口监控精灵是用于 RS232 / RS422 / RS485 端口监控的专业 强大的系统实用程序软件.CEIWEI  CommMonitor 监控显示, ...

  3. 大数据之路week06--day03(jdk8新特性 Lambda表达式)

    为什么使用Lambda表达式?(做为初学者接触这个新的语法,会很懵逼,说道理,我在接触到这一块的时候,语法规则我看到了也很懵逼,因为这个和逻辑的关系不是很大,但就是作为一种新的语法出现,一时间很难接受 ...

  4. DT6.0二次最后一次开发插件-手机端熊掌号定时提交

    今天写完这个,就是DT6.0最后开放的插件,因为群里的朋友需要,就写了一个适合DT6的手机端定时插件.不过个人还是喜欢7.0的版本,7.0的插件在上几期分享了,今天就不过多说了! 我这个是初成品,改善 ...

  5. Java 中抽象类与接口的区别

    TypeScript 中的接口,有点类似抽象类的概念.Java 中抽象类属于包含属性与抽象行为,而接口通常只是抽象行为.抽象类可以实现模板模式. 参考 https://www.cnblogs.com/ ...

  6. SCOI2018 树

    树 时间限制 3000ms 内存限制 64MB [题目描述] 在大小为 N 的树上,点从 1 到 N 标号,第 i 个点有权值 Ai,现在需要支持两种操作: 第一种操作格式为"1 U&quo ...

  7. 判断变量是否不为空,函数isset()、!empty()与!is_null()的比较

    转载:https://blog.csdn.net/qq_38812954/article/details/79581785 判断变量的值,尤其是判断他们是否不为空,我们有以下4种方法: if(isse ...

  8. Codeforces#572 Div2 C---Candies!【倍增】【DP】【思维】

    题目:http://codeforces.com/contest/1189/problem/C 题意:给定n个数,每次查询一个区间$[l,r]$.对这个区间内的数,相邻两个数之和超过10,则得到一个c ...

  9. 51、[源码]-Spring容器创建-容器创建完成

    51.[源码]-Spring容器创建-容器创建完成 12.finishRefresh();完成BeanFactory的初始化创建工作:IOC容器就创建完成: 1).initLifecycleProce ...

  10. nginx配置url伪静态

    rewrite 规则 定向路径 重写类型; 举例: rewrite  (.*)/web/(.*)-(.*)-(.*).html$  $1/web/index.php?r=$2/$3/$4  last; ...