要实现多个线程执行完成先后,就要知道如何实现线程之间的等待,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:现有线程T1/T2/T3,如何确保T1执行完成之后执行T2,T3在T2执行完成之后执行。的更多相关文章

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

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

  2. T2 Func<in T1,out T2>(T1 arg)

    委托调用方法的4种方式. using System; using System.Collections.Generic; namespace ConsoleApplication1 { delegat ...

  3. Java多线程--线程安全问题的相关研究

    在刚刚学线程的时候我们经常会碰到这么一个问题:模拟火车站售票窗口售票.代码如下: package cn.blogs.com.isole; /* 模拟火车站售票窗口售票,假设有50张余票 */ publ ...

  4. Java多线程——线程范围内共享变量

    多个线程访问共享对象和数据的方式 1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做. package java_ ...

  5. java 多线程—— 线程等待与唤醒

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  6. java进程/线程;堆和栈;多线程

    一.进程和线程 进程:在内存中运行的应用程序,一个exe是一个进程. 如:ps -exf  可以查看各个应用的进程,其中ppid为父进程: ps aux | egrep '(cron|syslog)' ...

  7. Java面向对象 线程技术 -- 下篇

     Java面向对象 线程技术 -- 下篇 知识概要:              (1)线程间的通信           生产者 - 消费者 (2)生产者消费者案例优化 (3)守护线程 (4)停止线 ...

  8. Java面向对象 线程技术--上篇

     Java面向对象   线程 知识概要:                   (1)线程与进程 (2)自定义线程的语法结构 (3)多线程概念理解 (4)多线程状态图 (5)多线程--卖票 (6)同 ...

  9. Java基础——线程

    一. 进程 是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程. 比如在Windows系统中,一个运行的exe就是一个进程. 二.线程 是指进程中的一个执行流 ...

随机推荐

  1. PDF加密无法做笔记

    尝试打印PDF,若无法打印,可以利用PDFescape(http://www.pdfescape.com/) PDFescape是一个可以在线修改.做笔记的网站,但是在线使用有上传PDF大小限制(小于 ...

  2. Servlet的三个域对象

    我们在开发javaweb项目的时候,经常会遇到jsp和Servet之间互相传值,既然有传值,就要有对象来传,这里先说Servlet的三大域对象,request,session,application他 ...

  3. 【Darwin】 越狱后玩耍IPhone系统

    玩耍IOS系统 大家都知道IOS是自Mac OS修改而来的.而Mac OS和IOS的共同核心是Darwin,其基于FreeBSD发展而来,整体而言也是个类Unix系统.之前把自己的手机越狱之后正好开始 ...

  4. 配置COCO API(安装COCO)

    仍旧是win10,Python3.5 从GitHub下载coco源码,解压到任意文件夹.(或者创建一个工程)coco源码链接 https://github.com/cocodataset/cocoap ...

  5. PHP 密码重置,发送邮件,随机长度字母数字密码

    <?php include ("database.php"); require_once ('email.class.php'); date_default_timezone ...

  6. Suricata默认规则集相关

    Suricata规则集 Suricata 基于规则检测和控制数据流量,所有规则的配置文件保存在rules目录内 .这些是已知和确认的活动僵尸网络和其C&C(command and contro ...

  7. Redis——主从同步原理

    刚接触到Redis,首先对Redis有一个初步的了解. 开源,免费,遵守BSD协议,key-value数据库. 可以将内存中的数据保存在磁盘中,重启的时候可以再次加载使用. 多种key-value类型 ...

  8. 如何在jenkins上新建一个项目及其简单配置

    1.首先,点击[新建]进入选择页面,如下图(一般选择"构建一个自由风格的软件项目")     2.填好项目名称后,点击ok,跳转至如下页面,可以在这个页面进行项目的配置(包括拉源码 ...

  9. Rails Migration Data Model栏位修改及数据类型介绍

    测试版本Ruby:2.3.1   Rails:5.0.1 一.增加栏位       给devise默认的用户新增增加username字段 $ rails generate migration add_ ...

  10. Alpha冲刺总结

    团队成员 陈家权 031502107 赖晓连 031502118 雷晶 031502119 林巧娜 031502125 庄加鑫 031502147 一.项目预期计划及现实进展 项目预期计划 现实进展 ...