【多线程:综合练习】

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

【多线程:综合练习】

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实现 处理的方式非常不同,可以仔细阅读 分析这两种方法

目录
相关文章
|
5月前
|
监控 Java 测试技术
Java并发编程最佳实践:设计高性能的多线程系统
Java并发编程最佳实践:设计高性能的多线程系统
81 1
|
7月前
|
算法 安全 Java
Java性能优化(四)-多线程调优-Synchronized优化
JVM在JDK1.6中引入了分级锁机制来优化Synchronized,当一个线程获取锁时,首先对象锁将成为一个偏向锁,这样做是为了优化同一线程重复获取导致的用户态与内核态的切换问题;其次如果有多个线程竞争锁资源,锁将会升级为轻量级锁,它适用于在短时间内持有锁,且分锁有交替切换的场景;轻量级锁还使用了自旋锁来避免线程用户态与内核态的频繁切换,大大地提高了系统性能;但如果锁竞争太激烈了,那么同步锁将会升级为重量级锁。减少锁竞争,是优化Synchronized同步锁的关键。
119 2
|
7月前
|
安全 Java 调度
Java并发编程:优化多线程应用的性能与安全性
在当今软件开发中,多线程编程已成为不可或缺的一部分,尤其在Java应用程序中更是如此。本文探讨了Java中多线程编程的关键挑战和解决方案,重点介绍了如何通过合理的并发控制和优化策略来提升应用程序的性能和安全性,以及避免常见的并发问题。
75 1
|
7月前
|
安全 程序员
多线程的6个综合练习
多线程的6个综合练习
50 0
|
6月前
|
Java 测试技术 容器
多线程编程基础与并发问题解决方案
多线程编程基础与并发问题解决方案
|
7月前
|
缓存 并行计算 安全
【并发编程系列一】并发编年史:线程的双刃剑——从优势到风险的全面解析
【并发编程系列一】并发编年史:线程的双刃剑——从优势到风险的全面解析
|
8月前
|
缓存 安全 Java
多线程--深入探究多线程的重点,难点以及常考点线程安全问题
多线程--深入探究多线程的重点,难点以及常考点线程安全问题
176 1
|
8月前
|
监控 Java 编译器
Go语言内存与并发性能综合优化策略
【2月更文挑战第11天】Go语言以其高效的并发处理能力和简洁的内存管理机制成为了现代软件开发中的热门选择。然而,在实际应用中,如何综合优化Go程序的内存使用和并发性能,仍然是一个值得探讨的话题。本文将深入探讨Go语言内存与并发性能的综合优化策略,包括内存布局优化、并发模式设计、资源池化以及性能监控与分析等方面,旨在帮助开发者全面提升Go程序的整体性能。
|
8月前
|
存储 缓存 监控
深入理解线程池:优化多线程任务管理与提升性能
深入理解线程池:优化多线程任务管理与提升性能
873 0
|
缓存 安全 Java
从CPU的视角看 多线程代码为什么那么难写!
当我们提到多线程、并发的时候,我们就会回想起各种诡异的bug,比如各种线程安全问题甚至是应用崩溃,而且这些诡异的bug还很难复现。我们不禁发出了灵魂拷问 “为什么代码测试环境运行好好的,一上线就不行了?”。 为了解决线程安全的问题,我们的先辈们在编程语言中引入了各种各样新名词,就拿我们熟悉的Java为例,不仅java语言自带了synchronized、volatile、wait、notify… ,jdk中各种工具包也是层出不穷,就比如单一个Lock,就可以有很多种实现,甚至很多人都谈锁色变。
93 0

相关实验场景

更多