java多线程入门(三)练习题中的使用

简介: java多线程入门(三)练习题中的使用

1.死锁



例子每个线程两个锁都要用到,但是每个线程分别拿了一个锁,然后获取另外的锁,但是当前锁得不到不释放。最终造成卡死的现象


public class TestThreadDeadlock implements Runnable {
  private static String lockA = "lockA";
  private static String lockB = "lockB";
  private AtomicInteger num = new AtomicInteger(1);
  @Override
  public void run() {
    if (num.get() % 2 == 1) {
      synchronized (lockA) {
        System.out.println("1获取A锁");
        num.set(2);
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        synchronized (lockB) {
          System.out.println("1获取B锁");
        }
      }
    } else {
      synchronized (lockB) {
        System.out.println("2获取B锁");
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        synchronized (lockA) {
          System.out.println("2获取A锁");
          num.set(1);
        }
      }
    }
  }
    public static void main(String[] args) throws InterruptedException {
      TestThreadDeadlock deadLock=new TestThreadDeadlock();
      Thread t1=new Thread(deadLock);
      Thread t2=new Thread(deadLock);
      t1.start();
      Thread.sleep(100);
      t2.start();
  }
}
复制代码


效果

网络异常,图片无法展示
|


2.join方法说明



  • join 方法可以让线程的并行变为串行
  • join 的作用是放弃当前的程序执行,去执行join的线程直到执行结束
  • join(long) 设置时间过后变并行 这里会释放锁的,sleep不释放的
  • join 放在start前面无意义
  • join 实现原理是wait


3.Semaphore信号量



  • 信号量可以控制并发访问的个数 例如生产5个可以并发的消费5个
  • 信号量和锁之间的区别是锁只有一个线程拿到锁,信号量可以是一批次的


Semaphore semaphore = new Semaphore(10,true);//可以有多少个请求 公平/非公平
semaphore.acquire();  //获取请求 阻塞的
semaphore.release();  //释放请求
复制代码


一个基于Semaphore客服的例子


4.wait/notify



5.Lock/Condition



可以声明多次:private static Condition c1 = lock.newCondition();

Condition.await();=Object.wait

Condition.await(long,timeUnit);=Object.wait(long)

Condition.signal();=Object.notify()

Condition.signalAll();=Object.notifyAll()

Codition和lock捆绑,wait/notify和同步块捆绑


6.LockSupport



  • LockSupport是一个线程阻塞工具类,所有的方法都是静态方法,
  • 和wait和notify的功能类似,wait/notify只能在同步块里面使用,LockSupport可以让线程在任意位置阻塞


// 唤醒下一个线程
 LockSupport.unpark(t1);
 // 当前线程阻塞
 LockSupport.park();
复制代码


7.新建 T1、T2、T3 三个线程,如何保证它们按顺序执行



大概逻辑就是T1执行、唤醒T2执行、唤醒T3执行

  • 根据上面学习用join


T1.start();
T1.join();
T2.start();
T2.join();
T3.start();
T3.join();
复制代码


  • 根据上面学习用信号量


Semaphore semaphore1=new Semaphore(1);
Semaphore semaphore2=new Semaphore(0);
Semaphore semaphore3=new Semaphore(0);
默认线程1可以拿到一个许可
线程1拿到许可执行,设置线程2
线程2拿到许可执行,设置线程3
线程3执行
复制代码


  • 根据上面的LockSupport


//执行
//唤醒t2
LockSupport.unpark(t2);
//当前阻塞
LockSupport.park();
//t2先阻塞
LockSupport.park();
//执行
//唤醒t3
LockSupport.unpark(t3);
//t3先阻塞
LockSupport.park();
//执行
//唤醒t1
LockSupport.unpark(t1);
复制代码


  • 锁加状态


/**
     * name 打印输出
     * targetNum 目标值的时候才匹配输出
     **/
    private void printLetter(String name, int targetNum) {
       //注意这里的循环是匹配状态后才++的 控制打印的次数
        for (int i = 0; i < times; ) {
            //获取锁
            lock.lock();
            //状态控制当为目标状态的时候输出
            if (state % 3 == targetNum) {
                state++;//另一个线程匹配
                i++;//循环打印的次数+1
                System.out.print(name);
            }
            lock.unlock();
        }
    }


相关文章
|
3天前
|
设计模式 前端开发 Java
【前端学java】SpringBootWeb极速入门-分层解耦(03)
【8月更文挑战第13天】SpringBootWeb极速入门-分层解耦(03)
8 2
【前端学java】SpringBootWeb极速入门-分层解耦(03)
|
4天前
|
开发框架 前端开发 Java
【前端学java】SpringBootWeb极速入门-实现一个简单的web页面01
【8月更文挑战第12天】SpringBootWeb极速入门-实现一个简单的web页面01
15 3
【前端学java】SpringBootWeb极速入门-实现一个简单的web页面01
|
4天前
|
JSON 前端开发 Java
【前端学java】SpringBootWeb极速入门-请求参数解析(02)
【8月更文挑战第12天】SpringBootWeb极速入门-请求参数解析(02)
10 1
【前端学java】SpringBootWeb极速入门-请求参数解析(02)
|
3天前
|
存储 缓存 安全
深度剖析Java HashMap:源码分析、线程安全与最佳实践
深度剖析Java HashMap:源码分析、线程安全与最佳实践
|
5天前
|
缓存 前端开发 JavaScript
一篇文章助你搞懂java中的线程概念!纯干货,快收藏!
【8月更文挑战第11天】一篇文章助你搞懂java中的线程概念!纯干货,快收藏!
13 0
一篇文章助你搞懂java中的线程概念!纯干货,快收藏!
|
3天前
|
算法 安全 Java
深入解析Java多线程:源码级别的分析与实践
深入解析Java多线程:源码级别的分析与实践
|
4天前
|
存储 监控 算法
掌握Java内存管理:从入门到精通
在Java的世界里,内存管理是程序运行的心脏。本文将带你走进Java内存管理的奥秘,从基础概念到高级技巧,一步步揭示如何优化你的Java应用。准备好迎接挑战,让我们共同揭开高效内存使用的面纱!
|
4天前
|
Java 程序员 调度
深入浅出Java多线程编程
Java作为一门成熟的编程语言,在多线程编程方面提供了丰富的支持。本文将通过浅显易懂的语言和实例,带领读者了解Java多线程的基本概念、创建方法以及常见同步工具的使用,旨在帮助初学者快速入门并掌握Java多线程编程的基础知识。
4 0
|
5天前
|
Java
java中获取当前执行线程的名称
这篇文章介绍了两种在Java中获取当前执行线程名称的方法:使用`Thread`类的`getName`方法直接获取本线程的名称,以及使用`Thread.currentThread()`方法获取当前执行对象的引用再调用`getName`方法。
|
5天前
|
Java 测试技术
Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
10 0