Java多线程——三个多线程案例总结

  非常经典的三道多线程案例

  1、写两个线程,一个线程打印1-52,另一个线程打印A~Z,
    打印顺序为:12A34B…5152Z

  2、编写一个程序,启动三个线程,三个线程的名称分别是A,B,C
    每个线程将自己的名称在屏幕上打印5遍,打印顺序是ABCABCABC…

  3、写3个线程,打印如下:
     *Thread-0
     *Thread-0@Thread-1
     *Thread-0@Thread-1#Thread-2
     *Thread-0@Thread-1#Thread-2Thread-0
     *Thread-0@Thread-1#Thread-2
Thread-0@Thread-1
     *Thread-0@Thread-1#Thread-2*Thread-0@Thread-1#Thread-2
     …

  仔细观察这三道题,就会发现这三道题其实是同一类型的题目,都是多个线程按照一定的顺序打印一些内容,解决多线程问题的关键是使用多线程的同步机制,而解决顺序问题的关键是使用“信号量”机制(操作系统中)

  1、多线程的同步机制采用synchronized锁机制,使用同步方法或同步代码块即可完成对多个线程访问共享内容的同步。

  2、“信号量”机制

    首先引入“信号量”的概念

  信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。为了完成这个过程,需要创建一个信号量VI,然后将Acquire Semaphore VI以及Release Semaphore VI分别放置在每个关键代码段的首末端。确认这些信号量VI引用的是初始创建的信号量。

    Java实现“信号量”
    让多个线程调用同一个线程类的不同的方法,而在这个线程类中设置一个标志量(flag),由flag的初始化及重新赋值来控制第一个线程的选择以及不同线程对应的不同方法的执行顺序

   该类型题的关键就在于怎样设置“信号量”来确保顺序,也需要采用多线程的同步来避免产生“脏数据”。

   题解1:

     package com.xiaoaxiao.test.thread_test.thread_practice;/*** Created by xiaoaxiao on 2019/7/15* Description: 写两个线程,一个线程打印1~52,另一个线程打印A~Z,*              打印顺序为:12A34B...5152Z*/class MyThread implements Runnable{private int flag = 1;private int count = 1;@Overridepublic void run() {if(flag == 1){printNum();}else {printLetter();}}public synchronized void printNum(){while (flag != 1){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print(2*count-1);System.out.print(2*count);flag = 2;notify();}public synchronized void printLetter(){while (flag != 2){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print((char)((count-1)+'A'));count++;flag = 1;notify();}}public class ThreadPractice1 {public static void main(String[] args) {MyThread mt = new MyThread();new Thread(()->{for (int i=0;i<26;i++){mt.printNum();}}).start();new Thread(()->{for(int i=0;i<26;i++){mt.printLetter();}}).start();}}
    注意:count++的位置应该是在一个完整的过程结束后执行,通过Lambda表达式的形式创建线程并执行。

   题解2:

     package com.xiaoaxiao.test.thread_test.thread_practice;/*** Created by xiaoaxiao on 2019/7/15* Description: 编写一个程序,启动三个线程,三个线程的名称分别是A,B,C*              每个线程将自己的名称在屏幕上打印5遍,打印顺序是ABCABC*/class Print{private int flag = 1;private int count = 0;public int getCount() {return count;}public synchronized void printA(){while (flag != 1){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print(Thread.currentThread().getName());count++;flag = 2;notifyAll();}public synchronized void printB(){while (flag != 2){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print(Thread.currentThread().getName());count++;flag = 3;notifyAll();}public synchronized void printC(){while (flag != 3){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print(Thread.currentThread().getName());count++;flag = 1;notifyAll();}}class MyThread3 implements Runnable{Print print = new Print();@Overridepublic void run() {while (this.print.getCount()<16){if(Thread.currentThread().getName().equals("A")){print.printA();}else if(Thread.currentThread().getName().equals("B")){print.printB();}else {print.printC();}}}}public class ThreadPractice2 {public static void main(String[] args) {MyThread3 mt = new MyThread3();Thread threadA = new Thread(mt,"A");Thread threadB = new Thread(mt,"B");Thread threadC = new Thread(mt,"C");threadA.start();threadB.start();threadC.start();}}
    注意:使用Print类只是对打印信息的封装,也可以将这些信息直接写在线程类中,但没有达到不同类“各司其职”的效果

   题解3:

     package com.xiaoaxiao.test.thread_test.thread_practice;/*** Created by xiaoaxiao on 2019/7/15* Description: 写3个线程,打印如下(利用SB,线程安全)* *Thread-0* *Thread-0@Thread-1* *Thread-0@Thread-1#Thread-2* *Thread-0@Thread-1#Thread-2*Thread-0* *Thread-0@Thread-1#Thread-2*Thread-0@Thread-1* Thread-0@Thread-1#Thread-2*Thread-0@Thread-1#Thread-2* ...*/class Print2 {private int flag = 1;private int count = 0;//    private StringBuffer sb = new StringBuffer();private StringBuilder sb = new StringBuilder();public int getCount() {return count;}public synchronized void printThread0() {while (flag != 1) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}sb.append("*").append(Thread.currentThread().getName());System.out.println(sb);flag = 2;count++;notifyAll();}public synchronized void printThread1() {while (flag != 2) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}sb.append("@").append(Thread.currentThread().getName());System.out.println(sb.toString());flag = 3;count++;notifyAll();}public synchronized void printThread2() {while (flag != 3) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}sb.append("#").append(Thread.currentThread().getName());System.out.println(sb.toString());flag = 1;count++;notifyAll();}}class MyThread4 implements Runnable {Print2 print2 = new Print2();@Overridepublic void run() {while (this.print2.getCount() < 31) {if (Thread.currentThread().getName().equals("Thread-0")) {print2.printThread0();} else if (Thread.currentThread().getName().equals("Thread-1")) {print2.printThread1();} else {print2.printThread2();}}}}public class ThreadPractice3 {public static void main(String[] args) {MyThread4 mt = new MyThread4();Thread thread0 = new Thread(mt);Thread thread1 = new Thread(mt);Thread thread2 = new Thread(mt);thread0.start();thread1.start();thread2.start();}}
    注意:可以使用StringBuffer也可以使用StringBuilder,虽然StringBuffer是线程安全的,但是这里访问的已经是同步方法了,所以没有必要用StringBuffer,使用StringBuilder会大幅度提高程序的效率。

Java多线程——三个多线程案例总结相关推荐

  1. 【Java 多线程】多线程带来的的风险-线程安全、多线程五个经典案例

    日常开发中如果用到多线程编程,也一定会涉及到线程安全问题 线程安全这个问题就不太好理解 正因为如此,程序猿们才尝试发明出更多的编程模型来处理并发编程的任务 例如:多进程.多线程.actor.csp.a ...

  2. java多线程三之线程协作与通信实例

    多线程的难点主要就是多线程通信协作这一块了,前面笔记二中提到了常见的同步方法,这里主要是进行实例学习了,今天总结了一下3个实例: 1.银行存款与提款多线程实现,使用Lock锁和条件Condition. ...

  3. java 多线程 总结_java基础总结大全(三)多线程

    三.多线程: 1.进程和线程: 进程:正在进行的程序.每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元. 线程:进程内部的一条执行路径或者一个控制单元. 两者的区别: 一个进程 ...

  4. java多线程交替打印_使用Java实现三个线程交替打印0-74

    使用Java实现三个线程交替打印0-74 题目分析 三个线程交替打印,即3个线程是按顺序执行的.一个线程执行完之后,唤醒下一个线程,然后阻塞,等待被该线程的上一个线程唤醒.执行的顺序是一个环装的队列 ...

  5. java线程future_Java中多线程对运行结果怎么利用future获取

    Java中多线程对运行结果怎么利用future获取 发布时间:2020-12-07 17:11:08 来源:亿速云 阅读:124 作者:Leah Java中多线程对运行结果怎么利用future获取?针 ...

  6. Java多线程,Android多线程

    目录 一.线程的概念 二.线程创建的方式及特点 三.线程创建方式 1.继承Thread类 2.实现Runnable接口 3.实现Callable接口(我觉得了解即可) 4.AsyncTask异步任务( ...

  7. Java并发编程进阶——多线程的安全与同步

    多线程的安全与同步 多线程的操作原则 多线程 AVO 原则 A:即 Atomic,原子性操作原则.对基本数据类型变量的读和写是保证原子性的,要么都成功,要么都失败,这些操作不可中断. V:即 vola ...

  8. 多线程怎么保证数据安全_「软帝学院」Java挑战者专栏:多线程详解2

    软帝学院笔记Day21 多线程(单例设计模式)(掌握) 单例设计模式:保证类在内存中只有一个对象. 如何保证类在内存中只有一个对象呢? (1)控制类的创建,不让其他类来创建本类的对象.private ...

  9. java线程钥匙_Java多线程并发编程/锁的理解

    一.前言 最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测下会出现:库存超发/总库存与sku库存对不上等各种问题. 在运用了 限流/加锁等 ...

最新文章

  1. wp7 手机归属地查询
  2. unity 200.8m yoy_【Unity文档】Realtime GI介绍(一)
  3. 【floyd模板】哈利·波特的考试 (25 分)
  4. 51 nod 1127最短的包含字符串(尺取法)
  5. 新乡台达服务器驱动器维修,台达DELTA伺服驱动器维修
  6. 【项目升级】单库、多库、读写分离 · 任你选
  7. 7. Reverse Integer(反转整数)
  8. 华为防火墙ftp_常用的FTP两种模式,主动模式和被动模式,一分钟了解下
  9. 关于子元素连续数字和英文内容溢出父元素的问题
  10. 看看20万码农怎么评论:女生做程序员是一种怎样的体验?
  11. 如何合理封装你的轮子、飞机、大炮(以封装OkHttp为例)
  12. java 数组随机抽取_Java利用数组随机抽取幸运观众
  13. dnf连不上服务器删什么文件,DNF客户端又出问题?其实是这个文件惹的祸,删除就好了!...
  14. 互联网人求职向传统行业倾斜;全国有两成开发者月薪超1.7万 | 美通企业日报...
  15. 如何设置QQ和微信截图快捷键
  16. Thinkphp漏洞远程代码执行漏洞事件分析报告
  17. 育碧-彩虹六号如何绑定二次验证码/两步验证/身份验证?
  18. 给IDEA换个酷炫的主题,真的太好看了!
  19. thinkphp内核家教平台网站源码带手机站
  20. 采用igraph包分析网络数据

热门文章

  1. oracle 回滚操作
  2. 《道路交通安全违法行为计分分值》扣分情形
  3. 专访贝莱德CEO芬克:如何成为新一代华尔街教父
  4. 巴厘岛浪漫自在悠闲蜜月
  5. 浅学Html5CSS
  6. Java 图片转PDF 与 4张图片合并为一张
  7. 真香系列!Java工程师面试该怎么准备
  8. 如何把uni-app项目运行到小程序开发者工具?
  9. TI CC2530基础实验(定时器1查询方式——自由运行模式)
  10. 计算机一级考试正文首字下沉2行,各段落首字下沉两行、距正文0.1cm。