Day13:JAVA 多线程下
守护线程
线程分为用户线程和守护线程(daemon)
虚拟机必须确保用户线程执行完毕
Thread.setDaemon(boolean b); //如b=true则设置该线程为守护线程,默认false为用户线程
线程同步
并发:同一个对象被多个线程同时操作
同步形成条件:队列+锁
锁机制:synchronized
锁的对象是要变化的量
性能倒置:高优先级线程等待低优先级线程释放锁
同步方法
public synchronized void synMethod(){}
执行该方法则锁起this
若将一个大的方法申明为同步方法则会较大的浪费资源
同步块
synchronized(obj){}
锁的是obj
obj又称为同步监视器
死锁
多个线程互相抱着对方需要的资源不释放锁
产生死锁的四个必要条件:
-
互斥条件:一个资源每次只能被一个进程使用
-
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
-
不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺
-
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
只需要破掉上面任意一个或多个条件就可以避免死锁发生
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为线程池大小
-

浙公网安备 33010602011771号