【多线程:综合练习】

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

【多线程:综合练习】

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

目录
相关文章
|
Java 测试技术
干货|这些JMeter内置函数,你了解多少?建议收藏
干货|这些JMeter内置函数,你了解多少?建议收藏
207 1
|
存储 关系型数据库 MySQL
MySQL学习系列(6)-每天学习10个知识
MySQL学习系列(6)-每天学习10个知识
84 0
|
存储 C++
【PTA】L1-039 古风排版(C++)
【PTA】L1-039 古风排版(C++)
146 1
|
算法 Linux 调度
Linux源码阅读笔记03-调度器及CFS调度器
Linux源码阅读笔记03-调度器及CFS调度器
|
设计模式 JavaScript 前端开发
【Vue3】4个比较重要的设计模式!!
【Vue3】4个比较重要的设计模式!!
|
消息中间件 存储 Java
【RocketMQ系列一】初识RocketMQ
【RocketMQ系列一】初识RocketMQ
151 1
|
索引 Python
使用Python的Pandas库进行数据透视表(pivot table)操作
使用Python Pandas进行数据透视表操作包括:安装Pandas库,导入库,创建或读取数据,如`pd.DataFrame()`或从文件读取;然后使用`pd.pivot_table()`创建透视表,指定数据框、行索引、列索引和值,例如按姓名和科目分组计算平均分;查看结果通过打印数据透视表;最后可使用`to_csv()`等方法保存到文件。这为基础步骤,可按需求调整参数实现更多功能。
580 2
|
10月前
fireworks怎么进行图片坐标识别?
fw查看图片的坐标的技巧
176 6
|
存储 SQL Cloud Native
一文教会你使用强大的ClickHouse物化视图
在现实世界中,数据不仅需要存储,还需要处理。处理通常在应用程序端完成。但是,有些关键的处理点可以转移到ClickHouse,以提高数据的性能和可管理性。ClickHouse中最强大的工具之一就是物化视图。在这篇文章中,我们将探秘物化视图以及它们如何完成加速查询以及数据转换、过滤和路由等任务。 如果您想了解更多关于物化视图的信息,我们后续会提供一个免费的培训课程。
28640 10
一文教会你使用强大的ClickHouse物化视图
|
索引 Python
Python for循环中使用index索引
Python for循环中使用index索引
1534 0