目的

  • 如何让两个线程依次执行?
  • 那如何让 两个线程按照指定方式有序交叉运行呢?
  • 四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的
  • 三个运动员各自准备,等到三个人都准备好后,再一起跑
  • 子线程完成某件任务后,把得到的结果回传给主线程

1.如何让两个线程依次执行?

    public static void main(String[] args) {
demo1();
/*
结果: t1>>pirnt:1
t2>>pirnt:1
t2>>pirnt:2
t1>>pirnt:2
t1>>pirnt:3
t2>>pirnt:3
*/
demo1_1();
/*
结果:
t1>>pirnt:1
t1>>pirnt:2
t1>>pirnt:3
t2>>pirnt:1
t2>>pirnt:2
t2>>pirnt:3
*/
} public static void demo1() {
// 线程一
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
printNumber("t1");
}
}); // 线程二
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
printNumber("t2");
}
}); // 启动线程
t1.start();
t2.start();
} public static void demo1_1() {
// 线程一
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
printNumber("t1");
}
}); // 线程二
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
// 等到线程一执行完,再执行线程二
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
printNumber("t2");
}
}); // 启动线程
t1.start();
t2.start();
} /**
* 线程调用的方法
* @param threadName
*/
public static void printNumber(String threadName) {
int i = 0;
while (i++ < 3) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println(threadName+">>pirnt:"+i);
}
}

2. 那如何让 两个线程按照指定方式有序交叉运行呢?

这里可以使用同一个锁控制,然后调用wait()方法,和notify()方法

线程一打印1,然后线程二打印1,2,3 线程一在打印2,3

    public static void demo2() {
// 创建一个对象,用来作为锁
final Object objLock = new Object(); //线程一
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// 同步代码块
synchronized (objLock){
System.out.println("t1>>print:1");
try {
objLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 线程二执行完,唤醒线程一
System.out.println("t1>>print:2");
System.out.println("t1>>print:3");
}
}
}); // 线程二
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (objLock) {
// 线程二输出内容
System.out.println("t2>>print:1");
System.out.println("t2>>print:2");
System.out.println("t2>>print:3");
// 唤醒wait中的线程
objLock.notify();
}
}
}); // 启动线程
t1.start();
t2.start(); } 结果:
t1>>print:1
t2>>print:1
t2>>print:2
t2>>print:3
t1>>print:2
t1>>print:3

3.四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的

  1. 创建一个计数器,设置初始值,CountdownLatch countDownLatch = new CountDownLatch(2);
  2. 在 等待线程 里调用 countDownLatch.await() 方法,进入等待状态,直到计数值变成 0;
  3. 在 其他线程 里,调用 countDownLatch.countDown() 方法,该方法会将计数值减小 1;
  4. 当 其他线程 的 countDown() 方法把计数值变成 0 时,等待线程 里的 countDownLatch.await() 立即退出,继续执行下面的代码。

    CountDownLatch 适用于一个线程去等待多个线程的情况。
    public static void runDAfterABC() {
// 定义计数器的计数值
int worker = 3;
// 创建计数器
final CountDownLatch countDownLatch = new CountDownLatch(worker); // 创建线程D
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("D线程等待ABC线程运行。。。。");
try {
// 线程等待
countDownLatch.await();
System.out.println("ABC线程运行完,D线程运行");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start(); // 创建ABC线程
for (char threadName='A'; threadName<='C'; threadName++) {
// char转换为String
final String tN = String.valueOf(threadName); //创建线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程"+tN+"运行中。。");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程"+tN+"结束");
// 计数器减一
countDownLatch.countDown();
}
}).start();
}
} 结果: D线程等待ABC线程运行。。。。
线程A运行中。。
线程C运行中。。
线程B运行中。。
线程A结束
线程C结束
线程B结束
ABC线程运行完,D线程运行



4. 线程 A B C 各自开始准备,直到三者都准备完毕,然后再同时运行

  1. 先创建一个公共 CyclicBarrier 对象,设置 同时等待 的线程数,CyclicBarrier cyclicBarrier = new CyclicBarrier(3);

2)这些线程同时开始自己做准备,自身准备完毕后,需要等待别人准备完毕,这时调用 cyclicBarrier.await(); 即可开始等待别人;

3) 当指定的 同时等待 的线程数都调用了 cyclicBarrier.await();时,意味着这些线程都准备完毕好,然后这些线程才 同时继续执行。

    public static void runABCWhenAllReady() {
// 定义运行线程数
int runner = 3; // 创建CyclicBarrier 对象
final CyclicBarrier cyclicBarrier = new CyclicBarrier(runner);
// 创建随机数类,产生准备时间
final Random random = new Random();
// 创建线程
for (char threadName='A'; threadName <= 'C'; threadName++) {
final String tN = String.valueOf(threadName);
new Thread(new Runnable() {
@Override
public void run() {
// 随机生成准备时间
long prepareTime = random.nextInt(1000)+100;
System.out.println("线程"+tN+"准备中。。"); try {
Thread.sleep(prepareTime);
System.out.println("线程"+tN+"准备完成,等待其他线程!");
// 线程准备完毕
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
// 所有线程准备好后,运行
System.out.println("线程"+tN+"运行中。。");
}
}).start();
}
} 结果:
线程A准备中。。
线程B准备中。。
线程C准备中。。
线程A准备完成,等待其他线程!
线程C准备完成,等待其他线程!
线程B准备完成,等待其他线程!
线程A运行中。。
线程B运行中。。
线程C运行中。。

5. 子线程运行完后,将结果返回给主线程

实现接口类:Callable,在 v call()方法中编写运行代码

将结果返回主线程,使用 FutureTask 类的 get 方法,将数据传回去,

get方法会阻塞线程,然后call方法执行

    public static void doTaskWithResultInWorker() {
// 创建Callable对象
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
// 创建任务
System.out.println("任务开始");
int result = 0;
for (int i=0; i<=100; i++) {
result += i;
}
System.out.println("任务结束,返回结果");
// 返回结果
return result;
}
}; // 创建FutureTask,获取返回值
FutureTask<Integer> futureTask = new FutureTask<Integer>(callable);
// 启动线程
new Thread(futureTask).start(); // 线程阻塞,获取返回值
try {
System.out.println("结果:"+futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
} 结果:
任务开始
任务结束,返回结果
结果:5050

java多线程之间的通信的更多相关文章

  1. 多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)

    一.多线程之间的通信. 就是多个线程在操作同一份数据, 但是操作的方法不同. 如: 对于同一个存储块,其中有两个存储位:name   sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据. ...

  2. Java多线程——线程间通信

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...

  3. java线程之间的通信

    1.常用的方法 sleep() 该线程进入等待状态,不释放锁 wait() 该线程进入等待状态,释放锁 notify() 随机唤醒一个线程 notifyAll() 唤醒全部线程 getName() 获 ...

  4. java多线程之间的顺序问题

    java 多线程: 这样写有问题的:这样写可以的: package com.test; import java.util.concurrent.CountDownLatch; import java. ...

  5. JAVA多线程之间共享数据BlockingQueue介绍

    在JAVA的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利. ...

  6. 【关于java多线程和socket通信的一些记录】---高并发/高负载/高可用/重入锁

    多线程:提高cpu的使用效率,多线程是指在同一程序中有多个顺序流在执行. 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程. 线程:同一类线 ...

  7. java 多线程:线程通信-等待通知机制wait和notify方法;(同步代码块synchronized和while循环相互嵌套的差异);管道通信:PipedInputStream;PipedOutputStream;PipedWriter; PipedReader

    1.等待通知机制: 等待通知机制的原理和厨师与服务员的关系很相似: 1,厨师做完一道菜的时间不确定,所以厨师将菜品放到"菜品传递台"上的时间不确定 2,服务员什么时候可以取到菜,必 ...

  8. java 多线程 day04 线程通信

    package com.czbk.thread; /** * Created by chengtao on 17/12/3. * 需求: 子线程先运行10次,然后主线程运行 100次,依次运行50次 ...

  9. java多线程(线程通信-等待换新机制-代码优化)

    等待唤醒机制涉及方法: wait():让线程处于冻结状态,被wait的线程会被存储到线程池中. noticfy():唤醒同一个线程池中一个线程(任意也可能是当前wait的线程) notifyAll() ...

随机推荐

  1. PostgreSQL与mysql的比较

    特性 MySQL PostgreSQL 实例 通过执行 MySQL 命令(mysqld)启动实例.一个实例可以管理一个或多个数据库.一台服务器可以运行多个 mysqld 实例.一个实例管理器可以监视 ...

  2. MOOC(14)- 从数据库中获取预期结果

    数据库中的预期结果写的是SQL语句 从表格中读取到SQL语句,再去数据库获取真正的预期结果 # -*- coding: utf-8 -*- # @Time : 2020/2/18 9:50 # @Fi ...

  3. 关于RFC

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/byxdaz/article/details/557902关于RFC(Request For Comm ...

  4. Metasploit MS15-020漏洞利用

    title date tags layout Metasploit MS15-020漏洞利用 2018-05-06 Metasploit post 环境: 共享机/受害者:windows xp IP: ...

  5. jQuery插件开发小结

    jQuery插件开发规范 1. 使用闭包 (function($) { // Code goes here })(jQuery); 这是来自jQuery官方的插件开发规范要求,使用这种编写方式有什么好 ...

  6. AngularJS前端以ArrayBuffer类型请求后端数据以生成文件时,出现异常的处理

    .error(function(error){ var decodedString = String.fromCharCode.apply(null, new Uint8Array(error)); ...

  7. MOOC(7)- case依赖、读取json配置文件进行多个接口请求-完整的测试类,含依赖测试(15)

    ddt.依赖测试.断言.测试数据写回 # -*- coding: utf-8 -*- # @Time : 2020/2/12 23:07 # @File : test_class_15.py # @A ...

  8. inventor安装未完成,某些产品无法安装的解决方法

    inventor提示安装未完成,某些产品无法安装该怎样解决呢?,一些朋友在win7或者win10系统下安装inventor失败提示inventor安装未完成,某些产品无法安装,也有时候想重新安装inv ...

  9. Java IO: ByteArray和Filter

    作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) 本小节会简要概括Java IO中字节数组与过滤器的输入输出流,主要涉及以下4个类型的流:ByteArr ...

  10. Mybatis/ibatis基础知识

    Tip:mapper.xml中sql语句不允许出现分号! 1.#和$符号的区别 #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号.如:order by #user_id#,如果传入的值是 ...