Day13:JAVA 多线程下

Day13:JAVA 多线程下

守护线程

线程分为用户线程和守护线程(daemon)

虚拟机必须确保用户线程执行完毕

虚拟机不用等待守护线程执行完毕

Thread.setDaemon(boolean b); //如b=true则设置该线程为守护线程,默认false为用户线程

线程同步

并发:同一个对象被多个线程同时操作

同步形成条件:队列+锁

锁机制:synchronized

锁的对象是要变化的量

性能倒置:高优先级线程等待低优先级线程释放锁

同步方法

public synchronized void synMethod(){}

执行该方法则锁起this

若将一个大的方法申明为同步方法则会较大的浪费资源

同步块

synchronized(obj){}

锁的是obj

obj又称为同步监视器

死锁

多个线程互相抱着对方需要的资源不释放锁

产生死锁的四个必要条件:

  1. 互斥条件:一个资源每次只能被一个进程使用

  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放

  3. 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺

  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系

只需要破掉上面任意一个或多个条件就可以避免死锁发生

Lock(锁)

  • jdk1.5,通过显示定义同步锁对象来实现同步,同步锁使用Lock对象充当

  • java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具,锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象

  • ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁

定义可重入锁

porivate final ReentrantLock lock = new ReentrantLock();

加锁:lock.lock()

释放锁:lock.unlock() //通常放在finally块里面

synchronzied与Lock的对比

  • Lock是显式锁(手动开启和关闭锁,别忘记关闭锁),synchronized是隐式锁,除了作用域自动释放

  • Lock只有代码块锁,synchronized有代码块锁和方法锁

  • 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类)

  • 优先使用顺序:

    • Lock > 同步代码块(已经进入了方法体,分配了相应资源) > 同步方法(在方法体之外)

JUC为JAVA并发包

java.util.concurrent包下的CopyOnWriteArrayList类是线程安全的

Callable另一种使用方法:

  • A类实现Callable<T>,重写T call

  • FutureTask<T> ft = new FutureTask<T>(new A())

  • new Thread(ft).start()

可以接收返回值:

T t = ft.get(); //需要捕获异常

线程通信

方法

wait() //表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁

wait(long timeout) //指定等待的毫秒数

notify() //唤醒一个处于等待状态的线程

notifyAll() //唤醒同一个对象上所有调用wait()方法的线程,优先级高的线程优先调度

注意:均是Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常IllegalMonitorStateException

管程法

设置缓冲区

信号灯法

设置标志位

线程池

  • 背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大

  • 思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完返回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。

  • 好处:

    • 提高响应速度(减少了创建新线程的时间)

    • 降低资源消耗(重复利用线程池中的线程,不需要每次都创建)

    • 便于线程管理(。。。)

      • corePoolSize:核心池的大小

      • maximumPoolSize:最大线程数

      • KeepAliveTime:线程没有任务时最多保持多长时间后会终止

使用

JDK5.0:ExecutorService和Executors

  • ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor

    • void execute(Runnable command):执行任务/命令,没有返回值,一般用来执行Runnable

    • <T> Future<T> submit(Callable<T> task):执行任务,有返回值,一般用来执行Callable

    • void shutdown():关闭线程池

  • Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池

    • ExecutorService newFixedThreadPool(int i):i为线程池大小

posted @ 2021-06-08 21:33  Layman52  阅读(42)  评论(0)    收藏  举报