三则案例,助你掌握多线程 | 带你学《Java语言高级特性》之十五

简介: 经历了前几节的学习,相信你已经对多线程有了自己的见解,现在,跟作者一起实操三则案例,助你快速消化所学知识吧!

上一篇:另类的“同步”-volatile关键字 | 带你学《Java语言高级特性》之十四
【本节目标】
通过阅读本节内容,你将通过数字加减、生产电脑、竞争抢答三则案例的多线程相关逻辑实现,进一步掌握多线程开发的相关能力,对线程的各类操作更加得心应手。

多线程案例分析一:数字加减

设计4个线程对象,两个线程执行减操作,两个线程执行加操作。

public class ThreadDemo {
    public static void main(String[] args) throws Exception {
        Resource res = new Resource();
        SubThread st = new SubThread(res);
        AddThread at = new AddThread(res);
        new Thread(at, "加法线程-A ").start();
        new Thread(at, "加法线程-B ").start();
        new Thread(st, "减法线程-X ").start();
        new Thread(st, "减法线程-Y ").start();
    }
}
class AddThread implements Runnable {
    private Resource resource;
    public AddThread(Resource resource) {
        this.resource = resource;
    }
    @Override
    public void run() {
        for (int x = 0 ; x< 50 ; x++) {
            try {
                this.resource.add();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
class SubThread implements Runnable {
    private Resource resource;
    public SubThread(Resource resource) {
        this.resource = resource;
    }
    @Override
    public void run() {
        for (int x = 0 ; x < 50 ; x++) {
            try {
                this.resource.sub();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
class Resource {     //定义一个操作的资源
    private int num = 0;      //这个是要进行加减操作的数据
    private boolean flag = true;       //加减的切换
    //flag = true:表示可以进行加法操作,但是无法进行减法操作
    //flag = false:表示可以进行减法操作,但是无法进行加法操作
    public synchronized void add() throws Exception {      //执行加法操作
        if (this.flag == false) {         //现在需要执行的是减法操作,加法操作要等待
            super.wait();
        }
        Thread.sleep(100) ;
        this.num++ ;
        System.out.println("【加法操作 -" + Thread.currentThread().getName() + "】num = " + this.num) ;
        this.flag = false ;    //加法操作执行完毕,需要执行减法处理
        super.notifyAll() ;   //唤醒全部等待线程

    }
    public synchronized void sub() throws Exception {    //执行减法操作
        if (this.flag == true) {      //减法操作需要等待
            System.out.println("【减法操作 -" + 
Thread.currentThread().getName() + "】进行等待") ;
            super.wait() ;
        }
        Thread.sleep(200) ;
        this.num-- ;
        System.out.println("【减法操作 -" + Thread.currentThread().getName() + "】num = " + this.num) ;
        this.flag = true ;
        super.notifyAll() ;
    }
}

image.png
图一 多线程加减法操作

这是一个经典的多线程开发操作,这一个程序里面一定要考虑的核心本质在于:加一个、减一个,整体的计算结果应该在0、-1、1 中循环出现才是合理的。

多线程案例分析二:生产电脑

设计一个生产电脑和搬运电脑类,要求生产出一台电脑就搬走一台电脑,如果没有新的电脑生产出来,则搬运工需要等待新电脑产出;如果生产出的电脑没有搬走,则要等待电脑搬走再生产,并统计出生产的电脑数量。
在本程序中,就是一个标准的生产者与消费者的处理模型,那么下面实现具体的程序代码。

public class ThreadDemo {
    public static void main(String[] args) throws Exception {
        Resource res = new Resource() ;
        new Thread(new Producer(res)).start() ;
        new Thread(new Consumer(res)).start() ;
        new Thread(st).start() ;
        new Thread(st).start() ;
    }
}
class Producer implements Runnable {
    private Resource resource ;
    public Producer(Resource resource) {
        this.resource = resource ;
    }
    @Override
    public void run() {
        for (int x = 0; x < 50; x++) {
            try {
                this.resource.make() ;
            } catch (Exception e) {
                e.printStackTrace() ;
            }
        }
    }
}
class Consumer implements Runnable {
    private Resource resource ;
    public Consumer(Resource resource) {
        this.resource = resource ;
    }
    @Override
    public void run() {
        for (int x = 0 ; x < 50 ; x++) {
            try {
                this.resource.get() ;
            } catch (Exception e) {
                e.printStackTrace() ;
            }
        }
    }
}
class Resource {
    private Computer computer ;
    private boolean flag = true ;         //标记
    public synchronized void make() throws Exception {
        if (this.computer != null) {   //已经生产过了
            super.wait() ;
        }
        Thread.sleep(100) ;
        this.computer = new Computer("MLDN牌电脑", 1.1) ;
        System.out.println("【生产电脑】"+ this.computer) ;
        super.notifyAll() ;
    }
    public synchronized void get() throws Exception {
        if (this.computer == null) {    //没有生产过
            super.wait() ;
        }
        Thread.sleep(10) ;
        System.out.println("【取走电脑】"+ this.computer) ;
        this.computer = null ;    //已经取走了
        super.notifyAll() ;
    }
}
class Computer {
    private static int count = 0 ;    //表示生产的个数
    private String name ;
    private double price ;
    public Computer(String name, double price) {
        this.name = name ;
        this.price = price ;
        count++ ;
    }
    public String toString() {
        return "【第" + count + "台电脑】电脑名字:" + this.name + "价值:" + this.price ;
    }
}

image.png
图二 实现生产电脑

多线程案例分析三:竞争抢答

实现一个竞拍抢答程序:要求设置三个抢答者(三个线程),而后同时发出抢答指令,抢答成功者给出成功提示,未抢答成功者给出失败提示。

对于这个多线程操作,由于里面需要牵扯到数据返回问题,那么现在最好使用Callable是比较方便的一种处理形式。

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class ThreadDemo {
    public static void main(String[] args) throws Exception {
        MyThread mt = new MyThread();
        FutureTask<String> taskA = new FutureTask(mt);
        FutureTask<String> taskB = new FutureTask(mt);
        FutureTask<String> taskC = new FutureTask(mt);
        new Thread(taskA, "竞赛者A").start();
        new Thread(taskB, "竞赛者B").start();
        new Thread(taskC, "竞赛者C").start();
        System.out.println(taskA.get());
        System.out.println(taskB.get());
        System.out.println(taskC.get());
    }
}
class MyThread implements Callable<String> {
    private boolean flag = false;          //抢到处理
    @Override
    public String call() throws Exception {
        synchronized (this) {                //数据同步
            if (this.flag == false) {        //抢答成功
                this.flag = true;
                return Thread.currentThread().getName() + "抢答成功!" ;
            } else {
                return Thread.currentThread().getName() + "抢答失败!" ;
            }
        }
    }
}

image.png
图三 多线程竞答

想学习更多的Java的课程吗?从小白到大神,从入门到精通,更多精彩不容错过!免费为您提供更多的学习资源。
本内容视频来源于阿里云大学

下一篇:让String拥有变化之力 | 带你学《Java语言高级特性》之十六
更多Java面向对象编程文章查看此处

相关文章
|
1天前
|
安全 Java 调度
Java线程:深入理解与实战应用
Java线程:深入理解与实战应用
9 0
|
1天前
|
Java
Java中的并发编程:理解和应用线程池
【4月更文挑战第23天】在现代的Java应用程序中,性能和资源的有效利用已经成为了一个重要的考量因素。并发编程是提高应用程序性能的关键手段之一,而线程池则是实现高效并发的重要工具。本文将深入探讨Java中的线程池,包括其基本原理、优势、以及如何在实际开发中有效地使用线程池。我们将通过实例和代码片段,帮助读者理解线程池的概念,并学习如何在Java应用中合理地使用线程池。
|
5天前
|
安全 Java
深入理解 Java 多线程和并发工具类
【4月更文挑战第19天】本文探讨了Java多线程和并发工具类在实现高性能应用程序中的关键作用。通过继承`Thread`或实现`Runnable`创建线程,利用`Executors`管理线程池,以及使用`Semaphore`、`CountDownLatch`和`CyclicBarrier`进行线程同步。保证线程安全、实现线程协作和性能调优(如设置线程池大小、避免不必要同步)是重要环节。理解并恰当运用这些工具能提升程序效率和可靠性。
|
6天前
|
前端开发 Java Go
开发语言详解(python、java、Go(Golong)。。。。)
开发语言详解(python、java、Go(Golong)。。。。)
|
6天前
|
安全 Java
java多线程(一)(火车售票)
java多线程(一)(火车售票)
|
6天前
|
人工智能 前端开发 Java
Java语言开发的AI智慧导诊系统源码springboot+redis 3D互联网智导诊系统源码
智慧导诊解决盲目就诊问题,减轻分诊工作压力。降低挂错号比例,优化就诊流程,有效提高线上线下医疗机构接诊效率。可通过人体画像选择症状部位,了解对应病症信息和推荐就医科室。
49 10
|
6天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
6天前
|
安全 Java 调度
Java并发编程:深入理解线程与锁
【4月更文挑战第18天】本文探讨了Java中的线程和锁机制,包括线程的创建(通过Thread类、Runnable接口或Callable/Future)及其生命周期。Java提供多种锁机制,如`synchronized`关键字、ReentrantLock和ReadWriteLock,以确保并发访问共享资源的安全。此外,文章还介绍了高级并发工具,如Semaphore(控制并发线程数)、CountDownLatch(线程间等待)和CyclicBarrier(同步多个线程)。掌握这些知识对于编写高效、正确的并发程序至关重要。
|
6天前
|
安全 Java 程序员
Java中的多线程并发编程实践
【4月更文挑战第18天】在现代软件开发中,为了提高程序性能和响应速度,经常需要利用多线程技术来实现并发执行。本文将深入探讨Java语言中的多线程机制,包括线程的创建、启动、同步以及线程池的使用等关键技术点。我们将通过具体代码实例,分析多线程编程的优势与挑战,并提出一系列优化策略来确保多线程环境下的程序稳定性和性能。
|
7天前
|
缓存 分布式计算 监控
Java并发编程:深入理解线程池
【4月更文挑战第17天】在Java并发编程中,线程池是一种非常重要的技术,它可以有效地管理和控制线程的执行,提高系统的性能和稳定性。本文将深入探讨Java线程池的工作原理,使用方法以及在实际开发中的应用场景,帮助读者更好地理解和使用Java线程池。

热门文章

最新文章