LeetCode多线程总结

1.LeetCode 1114 按序打印

题目:设计修改程序,以确保 two() 方法在 one() 方法之后被执行,three() 方法在 two() 方法之后被执行。

方法1:

用两个boolean变量flag1和flag2控制,当第一个线程结束,flag1=true;

线程2只有当flag1=true时,才能执行;

线程3只有当flag2=true时,才能执行。

方法2:join

获取执行first的线程t1和执行second的线程t2,t1和t2初始值为null;

当获取到t1时,t2会等到t1执行完才继续执行;

同样,t3会等到t2执行完之后,才会执行。

方法3:wait/notifyAll

使用整型变量mark控制线程2和线程3的执行顺序,

wait/notifyAll方法需要配合synchronized代码块使用,线程1执行之后,会释放锁。

 
 

方法4:CountDownLatch

用两个CountDownLatch实现,当第一个线程执行完毕,latch1减1为0,线程2就会被激活,当线程2执行完成,latch2减1为0,线程3就会被激活。

 
 

 

2.Leetcode 1195 交替打印字符串

题目:编写一个可以从 1 到 n 输出代表这个数字的字符串的程序,但是:

  1. 如果这个数字可以被 3 整除,输出 "fizz"。
  2. 如果这个数字可以被 5 整除,输出 "buzz"。
  3. 如果这个数字可以同时被 3 和 5 整除,输出 "fizzbuzz"。

请你实现一个有四个线程的多线程版  FizzBuzz, 同一个 FizzBuzz 实例会被如下四个线程使用:

  1. 线程A将调用 fizz() 来判断是否能被 3 整除,如果可以,则输出 fizz。
  2. 线程B将调用 buzz() 来判断是否能被 5 整除,如果可以,则输出 buzz。
  3. 线程C将调用 fizzbuzz() 来判断是否同时能被 3 和 5 整除,如果可以,则输出 fizzbuzz。
  4. 线程D将调用 number() 来实现输出既不能被 3 整除也不能被 5 整除的数字。

方法1:wait/notifyAll

给出一个数n,要遍历从1到n所有的数,这里用mark来表示每次遍历到的数,

4个线程之间是并行关系,

线程A的功能是找到只能被3且不能被5整除的数,否则就等待;

线程B的功能是找到只能被5且不能被3整除的数,否则就等待;

线程C的功能是找到只能被15整除的数,否则就等待;

线程D的功能是找到不能被3或5整除的数,否则就等待;

方法2:semaphore

利用4个信号量实现,其中用number线程充当入口(信号量初始为1);

在number线程中先判断数字满足哪一个条件,如果满足其一,就将对应的信号量+1,

使得对应的线程获取到信号量,执行输出语句,然后释放number的信号量。

 
 

 

3.Leetcode 1115 交替打印FooBar

题目:我们提供一个类:

1
2
3
4
5
6
7
8
9
10
11
12
13
class FooBar {
public void foo() {
    for (int i = 0; i < n; i++) {
      print("foo");
  }
}
 
public void bar() {
    for (int i = 0; i < n; i++) {
      print("bar");
    }
}
}

两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。

请设计修改程序,以确保 "foobar" 被输出 n 次。

方法1:boolean变量+yield

用boolean变量isPrint控制线程先后,这里不用isPrint,执行会超时。

方法2:wait/notify

用布尔型变量isPrint来控制两个线程的调用顺序

方法3:CountDownLatch

用两个CountDownLatch相互限制

  

 

 

 

方法4:semaphore

两个线程互相控制对方的信号量,当一个线程执行完,释放另一个线程的信号量,并且等待自己的信号量。

 
 

 

4.Leetcode 1116 打印零与奇偶数

题目:假设有这么一个类:

1
2
3
4
5
6
class ZeroEvenOdd {
  public ZeroEvenOdd(int n) { ... }  // 构造函数
  public void zero(printNumber) { ... } // 仅打印出 0
  public void even(printNumber) { ... } // 仅打印出 偶数
  public void odd(printNumber) { ... } // 仅打印出 奇数
}

相同的一个 ZeroEvenOdd 类实例将会传递给三个不同的线程:

  1. 线程 A 将调用 zero(),它只输出 0 。
  2. 线程 B 将调用 even(),它只输出偶数。
  3. 线程 C 将调用 odd(),它只输出奇数。

每个线程都有一个 printNumber 方法来输出一个整数。请修改给出的代码以输出整数序列 010203040506... ,其中序列的长度必须为 2n。 

方法1:semaphore

设置3个semaphore

先执行zeroSema输出0,再判断奇偶数;

如果是奇数就执行evenSema,计算1,3,5,...,n;

如果是偶数就执行oddSema,计算2,4,6,...,n;

每次奇偶数进程执行后,释放zeroSema,重新判断奇偶数。

     
posted @   nxf_rabbit75  阅读(519)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
1.LeetCode 1114 按序打印2.Leetcode 1195 交替打印字符串3.Leetcode 1115 交替打印FooBar4.Leetcode 1116 打印零与奇偶数
点击右上角即可分享
微信分享提示