面试复盘
1、写一个死锁
java
package Thread; /* * 死锁产生条件:多线程,多个锁,锁嵌套*/ public class DeadLockDemo { public static void main(String[] args) { //两个不同的锁对象 Object obj1=new Object(); Object obj2=new Object(); new Thread(new Runnable() { @Override public void run() { String name = Thread.currentThread().getName(); synchronized(obj1){//在拿到锁1的基础上去拿锁2 System.out.println(name+"拿到锁1,想要锁2"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj2){ System.out.println(name+"拿到了锁2"); } } } },"线程A").start(); new Thread(new Runnable() { @Override public void run() { String name = Thread.currentThread().getName(); synchronized (obj2){//在拿到锁2的基础上去拿锁1 System.out.println(name+"拿到了锁2,想要锁1"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized(obj1){ System.out.println(name+"拿到了锁1"); } } } },"线程B").start(); } }
2、写一个生产消费模型
java
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; /** * 使用 BlockQueue 实现生产者消费模型 */ public class BlockQueueTest { public static Integer count = 0; //创建一个阻塞队列 final BlockingQueue blockingQueue = new ArrayBlockingQueue<>(10); public static void main(String[] args) { BlockQueueTest testMain = new BlockQueueTest(); new Thread(testMain.new Producer()).start(); new Thread(testMain.new Consumer()).start(); } class Producer implements Runnable{ @Override public void run(){ for (int i = 0; i <10; i++) { try{ Thread.sleep(3000); }catch (Exception e){ e.printStackTrace(); } try{ blockingQueue.put(1); count++; System.out.println(Thread.currentThread().getName() + "生产者生产,目前总共有 " + count); }catch (InterruptedException e){ e.printStackTrace(); } } } } class Consumer implements Runnable{ @Override public void run(){ for (int i = 0; i <10; i++) { try{ Thread.sleep(3000); }catch (InterruptedException e){ e.printStackTrace(); } try{ blockingQueue.take();//消费 count--; System.out.println(Thread.currentThread().getName() + " 消费者消费,目前总共有 "+ count); }catch (InterruptedException e){ e.printStackTrace(); } } } } }
go:
package main import "fmt" func producer(out chan <- int) { for i:=0; i<10; i++{ data := i*i fmt.Println("生产者生产数据:", data) out <- data // 缓冲区写入数据 } close(out) //写完关闭管道 } func consumer(in <- chan int){ // 无需同步机制,先做后做 // 没有数据就阻塞等 for data := range in { fmt.Println("消费者得到数据:", data) } } func main(){ // 传参的时候显式类型像隐式类型转换,双向管道向单向管道转换 ch := make(chan int, 5) // 添加缓冲区,5 go producer(ch) // 子go程作为生产者 consumer(ch) // 主go程作为消费者 }
打印奇偶数
public class Test01 { private static int count; private static final Object lock = new Object(); private static final int num = 100; public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { while (count < num) { synchronized (lock) { if ((count % 2) == 0) { System.out.println(Thread.currentThread().getName() + ":" + count); count ++; } } } } }, "偶数").start(); new Thread(new Runnable() { @Override public void run() { while (count < num) { synchronized (lock) { if ((count % 2) == 1) { System.out.println(Thread.currentThread().getName() + ":" + count); count ++; } } } } }, "奇数").start(); } }
public class PrintOddEven2 { private static int count = 0; private static final Object object = new Object(); public static void main(String[] args) { new Thread(new printer(), "偶数线程,").start(); new Thread(new printer(), "奇数线程,").start(); } static class printer implements Runnable { @Override public void run() { while (count <= 100) { synchronized (object) { // 打印数字,并立即释放锁 System.out.println(Thread.currentThread().getName() + "打印:" + count++); object.notify(); // 此处判断,是为了打印完了100个数字后,程序能够正常结束,否则程序将一直等待下去,耗费系统资源。 if (count <= 100) { try { object.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } } }
go 交替打印
package main import ( "fmt" "sync" ) // PrintOddAndEven1 /* func PrintOddAndEven1() { //方法一,使用无缓冲的channel进行通信 var wg = new(sync.WaitGroup) //注意这里需要是指针go语言当中都是值传递 wg.Add(2) ch := make(chan struct{}) //无缓冲channel defer close(ch) maxVal := 100 go func() { defer wg.Done() for i := 1; i <= maxVal; i++ { ch <- struct{}{} if i%2 == 1 { //奇数 fmt.Printf("the odd is %d\n", i) } } }() go func() { defer wg.Done() for i := 1; i <= maxVal; i++ { <-ch //从管道当中读取一个数据 if i%2 == 0 { //偶数 fmt.Printf("the even is %d\n", i) } } }() wg.Wait() } func main() { PrintOddAndEven1() fmt.Println("over") }
交替打印字母数字
func main() { numChan := make(chan struct{}) defer close(numChan) var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() for num := 1; num <= 26; num++ { numChan <- struct{}{} fmt.Printf("%d", num) } }() go func() { defer wg.Done() for ch := 'A'; ch <= 'Z'; ch++ { <-numChan fmt.Printf("%s", string(ch)) } }() wg.Wait()
}
三个协程打印ABC
package main import ( "fmt" "sync" ) func main() { Achan := make(chan struct{}, 1) Bchan := make(chan struct{}, 1) Cchan := make(chan struct{}, 1) defer close(Achan) defer close(Bchan) defer close(Cchan) Achan <- struct{}{} counter := 0 maxVal := 10 exitChan := make(chan struct{}) //用于退出 go func() { for { <-Achan if counter >= maxVal { exitChan <- struct{}{} break } fmt.Printf("%s ", "A") counter++ Bchan <- struct{}{} } }() go func() { for { <-Bchan if counter >= maxVal { exitChan <- struct{}{} break } fmt.Printf("%s ", "B") counter++ Cchan <- struct{}{} } }() go func() { for { <-Cchan if counter >= maxVal { exitChan <- struct{}{} break } fmt.Printf("%s ", "C") counter++ Achan <- struct{}{} } }() <-exitChan }
参考
https://blog.csdn.net/qq_56999918/article/details/129214882