【多线程:综合练习】

简介: 【多线程:综合练习】

【多线程:综合练习】

01.介绍

我们提出两个问题 分别用wait/notify,park/unpark,await/signal解决。

02.问题一

介绍

我们创建两个线程 从1交替打印到10

wait/notify实现

@Slf4j(topic = "c.TestSun")
public class TestSun {
    public static void main(String[] args) {
        // 交替打印五轮
        TestNumber num = new TestNumber(5);
        new Thread(()->{
            num.print(true);
        },"t1").start();

        new Thread(()->{
            num.print(false);
        },"t2").start();
    }
}
@Slf4j(topic = "c.TestNumber")
class TestNumber{
    private int cnt = 1;
    private boolean flag = true;
    private final int count;
    public TestNumber(int count){
        this.count=count;
    }
    public void print(boolean flagN){
        synchronized (this){
            for (int i=0;i<count;i++){
                while (flag!=flagN){
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                log.debug("{}",cnt);
                cnt++;
                flag=!flag;
                this.notify();
            }
        }
    }
}

结果

23:45:24.559 c.TestNumber [t1] - 1
23:45:24.562 c.TestNumber [t2] - 2
23:45:24.562 c.TestNumber [t1] - 3
23:45:24.562 c.TestNumber [t2] - 4
23:45:24.562 c.TestNumber [t1] - 5
23:45:24.562 c.TestNumber [t2] - 6
23:45:24.562 c.TestNumber [t1] - 7
23:45:24.562 c.TestNumber [t2] - 8
23:45:24.562 c.TestNumber [t1] - 9
23:45:24.562 c.TestNumber [t2] - 10

park/unpark实现

@Slf4j(topic = "c.TestSunPark")
public class TestSunPark {
    static Thread t1;
    static Thread t2;
    public static void main(String[] args) {
        // 交替打印5次
        TestParkNum num = new TestParkNum(5);
        t1 = new Thread(()->{
            num.print(t2);
        },"t1");
        t2 = new Thread(()->{
            num.print(t1);
        },"t2");
        t1.start();
        t2.start();
        LockSupport.unpark(t1);
    }
}
@Slf4j(topic = "c.TestParkNum")
class TestParkNum{
    private int cnt = 1;
    private final int count;
    public TestParkNum(int count){
        this.count=count;
    }
    public void print(Thread next){
        for (int i=0;i<count;i++){
            LockSupport.park();
            log.debug("{}",cnt);
            cnt++;
            LockSupport.unpark(next);
        }
    }
}

结果

23:49:38.354 c.TestSunReenNum [t1] - 1
23:49:38.357 c.TestSunReenNum [t2] - 2
23:49:38.357 c.TestSunReenNum [t1] - 3
23:49:38.357 c.TestSunReenNum [t2] - 4
23:49:38.358 c.TestSunReenNum [t1] - 5
23:49:38.358 c.TestSunReenNum [t2] - 6
23:49:38.358 c.TestSunReenNum [t1] - 7
23:49:38.358 c.TestSunReenNum [t2] - 8
23:49:38.358 c.TestSunReenNum [t1] - 9
23:49:38.358 c.TestSunReenNum [t2] - 10

await/signal实现

public class TestSunReen {
    public static void main(String[] args) {
        // 交替打印5次
        TestSunReenNum num = new TestSunReenNum(5);
        Condition condition = num.newCondition();
        new Thread(()->{
            num.print(true,condition);
        },"t1").start();

        new Thread(()->{
            num.print(false,condition);
        },"t2").start();
    }
}
@Slf4j(topic = "c.TestSunReenNum")
class TestSunReenNum extends ReentrantLock {
    private int cnt = 1;
    private final int count;
    private boolean flag = true;
    TestSunReenNum(int count) {
        this.count = count;
    }
    public void print(boolean flagN, Condition condition){
        lock();
        try {
            for (int i=0;i<count;i++){
                while (flag!=flagN){
                    condition.await();
                }
                log.debug("{}",cnt);
                cnt++;
                flag=!flag;
                condition.signalAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            unlock();
        }
    }
}

结果

23:51:38.603 c.TestSunReenNum [t1] - 1
23:51:38.606 c.TestSunReenNum [t2] - 2
23:51:38.606 c.TestSunReenNum [t1] - 3
23:51:38.607 c.TestSunReenNum [t2] - 4
23:51:38.607 c.TestSunReenNum [t1] - 5
23:51:38.607 c.TestSunReenNum [t2] - 6
23:51:38.607 c.TestSunReenNum [t1] - 7
23:51:38.607 c.TestSunReenNum [t2] - 8
23:51:38.607 c.TestSunReenNum [t1] - 9
23:51:38.607 c.TestSunReenNum [t2] - 10

03.问题二

三个线程交替打印abc 5次

wait/notify实现

public class TestSun2 {
    public static void main(String[] args) {
        TestSun2Num num = new TestSun2Num(5);
        new Thread(()->{
            num.print("a",1);
        }).start();

        new Thread(()->{
            num.print("b",2);
        }).start();

        new Thread(()->{
            num.print("c",0);
        }).start();
    }
}

class TestSun2Num{
    private int cnt = 1;
    private final int count;
    public TestSun2Num(int count){
        this.count=count;
    }
    public void print(String str,int flag){
        synchronized (this){
            for (int i=0;i<count;i++){
                while (cnt%3!=flag){
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.print(str);
                if (flag==0)
                    System.out.println();
                cnt++;
                this.notifyAll();
            }
        }
    }
}

结果

abc
abc
abc
abc
abc

park/unpark实现

public class TestSun2Park {
    static Thread t1;
    static Thread t2;
    static Thread t3;
    public static void main(String[] args) {
        TestSun2ParkNum num = new TestSun2ParkNum(5);
        t1 = new Thread(()->{
            num.print(1,"a",t2);
        });

        t2 = new Thread(()->{
            num.print(2,"b",t3);
        });

        t3 = new Thread(()->{
            num.print(0,"c",t1);
        });
        t1.start();
        t2.start();
        t3.start();
        LockSupport.unpark(t1);
    }
}

class TestSun2ParkNum{
    private final int count;

    TestSun2ParkNum(int count) {
        this.count = count;
    }

    public void print(int flagN,String str,Thread next){
        for (int i=0;i<count;i++){
            LockSupport.park();
            System.out.print(str);
            if (str.equals("c"))
                System.out.println();
            LockSupport.unpark(next);
        }
    }
}

结果

abc
abc
abc
abc
abc

await/signal实现

public class TestSun2Reen {
    public static void main(String[] args) {
        TestReenNum num = new TestReenNum(5);
        Condition condition1 = num.newCondition();
        Condition condition2 = num.newCondition();
        Condition condition3 = num.newCondition();
        new Thread(()->{
            num.print("a",condition1,condition2);
        }).start();

        new Thread(()->{
            num.print("b",condition2,condition3);
        }).start();

        new Thread(()->{
            num.print("c",condition3,condition1);
        }).start();

        Sleeper.sleep(1);
        num.lock();
        try {
            condition1.signal();
        }finally {
            num.unlock();
        }
    }
}

class TestReenNum extends ReentrantLock {
    private final int count;
    TestReenNum(int count) {
        this.count = count;
    }
    public void print(String str, Condition condition,Condition nextCondition){
        lock();
        try {
            for (int i=0;i<count;i++){
                condition.await();
                System.out.print(str);
                if (str.equals("c"))
                    System.out.println();
                nextCondition.signalAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            unlock();
        }

    }
}

结果

abc
abc
abc
abc
abc

04.需要关注的

1.我们需要熟练使用上面几种方法。
2.问题一与问题二用await/signal实现 处理的方式非常不同,可以仔细阅读 分析这两种方法

目录
相关文章
|
24天前
|
监控 Java 测试技术
Java并发编程最佳实践:设计高性能的多线程系统
Java并发编程最佳实践:设计高性能的多线程系统
36 1
|
18天前
|
存储 监控 算法
深入探究Java线程池:提升并发性能的利器
在当今高度并发的应用开发中,Java线程池作为一种广泛应用的并发编程技术,提供了一种优雅且高效的线程管理方案。本文深入探究Java线程池的相关技术,涵盖其核心概念、优势、常见类型(如FixedThreadPool、CachedThreadPool、SingleThreadExecutor、ScheduledThreadPool、ForkJoinPool及WorkStealingPool)、核心参数配置、异常处理与监控方法,以及性能调优的最佳实践,帮助读者更好地理解和应用线程池,从而提升并发性能。
|
1月前
|
安全 Java API
揭秘Java并发编程的神秘面纱:线程安全与性能优化之间的微妙舞蹈,如何让你的程序在多核时代中翱翔!
【8月更文挑战第12天】随着多核处理器的普及,Java并发编程越发重要。线程安全确保多线程环境下的程序一致性,而性能优化则让程序高效运行。通过同步机制如`synchronized`关键字或`ReentrantLock`接口,我们可以实现线程安全,如在银行账户存款操作中限制并发访问。然而,过度同步会导致性能下降,因此采用细粒度锁和利用Java并发工具类(如`ConcurrentHashMap`)可提高程序的并发能力。理解这些概念并加以实践,是每个Java开发者提升技能的关键。
31 0
|
2月前
|
存储 Java 调度
线程操纵术并行策略问题之Java的并行编程优势问题如何解决
线程操纵术并行策略问题之Java的并行编程优势问题如何解决
|
3月前
|
安全 Java 调度
Java并发编程:优化多线程应用的性能与安全性
在当今软件开发中,多线程编程已成为不可或缺的一部分,尤其在Java应用程序中更是如此。本文探讨了Java中多线程编程的关键挑战和解决方案,重点介绍了如何通过合理的并发控制和优化策略来提升应用程序的性能和安全性,以及避免常见的并发问题。
45 1
|
3月前
|
安全 程序员
多线程的6个综合练习
多线程的6个综合练习
25 0
|
3月前
|
缓存 并行计算 安全
【并发编程系列一】并发编年史:线程的双刃剑——从优势到风险的全面解析
【并发编程系列一】并发编年史:线程的双刃剑——从优势到风险的全面解析
|
10月前
|
缓存 安全 Java
从CPU的视角看 多线程代码为什么那么难写!
当我们提到多线程、并发的时候,我们就会回想起各种诡异的bug,比如各种线程安全问题甚至是应用崩溃,而且这些诡异的bug还很难复现。我们不禁发出了灵魂拷问 “为什么代码测试环境运行好好的,一上线就不行了?”。 为了解决线程安全的问题,我们的先辈们在编程语言中引入了各种各样新名词,就拿我们熟悉的Java为例,不仅java语言自带了synchronized、volatile、wait、notify… ,jdk中各种工具包也是层出不穷,就比如单一个Lock,就可以有很多种实现,甚至很多人都谈锁色变。
75 0
【并发技术01】传统线程技术中创建线程的两种方式
【并发技术01】传统线程技术中创建线程的两种方式
|
安全 算法 Java
【并发编程技术】「技术辩证分析」在并发编程模式下进行线程安全以及活跃性问题简析
【并发编程技术】「技术辩证分析」在并发编程模式下进行线程安全以及活跃性问题简析
69 0
【并发编程技术】「技术辩证分析」在并发编程模式下进行线程安全以及活跃性问题简析