Java并发(1)

线程和进程的区别

每个进程拥有自己的一整套变量,而线程共享变量。

在有些操作系统中,线程更轻量级,创建,撤销一个线程比启动新进程的开销要小得多

启动线程

应该讲要运行的任务与运行机制解耦

Runnable r = new Runnable() {
    @Override
    public void run() {
    }
};
final Thread t = new Thread(r);
t.start();

interrupt方法请求终止线程

interrupt()方法用来请求终止线程,调用interrupt()时,中断状态(boolean类型)将被置位,每个线程应该不时检查这个状态。

while (!Thread.currentThread().isInterrupted()) {
    //do more work
}

如果线程被阻塞,调用interrupt()会抛出InterruptedException异常。如果已经调用了interrupt(),线程调用sleep()会清除中断状态位并抛出InterruptedException异常。

线程状态

new,用new操作符新建一个线程,线程还没开始运行,处于new状态

runnable,调用start(),线程处于runnable状态。可能正在运行,也可能没有运行,取决于操作系统给线程提供运行时间。

blocked,一个线程试图获取一个内部的对象锁,该锁被其他线程所持有,该线程进入阻塞状态。

waiting,线程等待另一个线程通知调度器一个条件时,进入等待状态。如调用Object.wait(),Condition.await()等

timed waiting,加超时参数,进入timed waiting状态,这一状态保持到超时期满或接受到适当的通知。

terminated,线程终止。终止的两种情况:run()正常退出自然死亡。因一个未捕获异常而意外死亡。

线程优先级

每个线程都有优先级,setPriority()设置,范围为1到10,默认为5。

每当线程调度器选择新线程时,会选择有较高优先级的线程。当虚拟机依赖于宿主机的线程实现机制时,Java线程优先级被映射到宿主机的线程优先级上,优先级个数也许更多,也许更少。

守护线程

Thread.setDaemon(true)将线程转为守护线程。守护线程的唯一用途是为其他线程提供服务,当只剩下守护线程时,虚拟机退出。

守护线程随时会发生中断。

竞争条件(race condition)

两个线程同时去更新一个对象,更新的过程不是原子操作,导致数据出现了讹误。

锁的种类

对象的内部锁。使用关键字synchronized,修饰方法,代码块,使用对象的内部锁,改锁只有一个条件。

ReentrantLock。java.util.concurrent包下的类。

ReentrantLock和条件对象

代码基本结构如下:

lock.lock();
try {
    //do something
} finally {
    lock.unlock();
}

ReentrantLock是可重入的,线程可以重复获得已持有的锁,锁保持一个持有计数(hold count)跟踪lock()和unlock()的嵌套调用。

条件对象,来管理那些已经获得了一个锁但是却不能做有效工作的线程。一个锁对象可以有一个或多个条件对象,通过newCondition()获得。

Condition myCondition = lock.newCondition();
myCondition.await();

await()使得线程进入waiting状态,并放弃了锁,调用await()的线程进入该条件对象的等待集。当锁可用时,线程不能马上解除阻塞,直到另一个线程调用同一个条件对象的signal(),signalAll()才行能。

signal(),signalAll()不会立即激活一个线程,仅仅是解除等待线程的阻塞,以便这些线程可以在当前线程退出同步方法后,通过竞争实现对对象的访问。

锁和条件

锁用来保护代码片段,任何时刻只能有一个线程执行被保护的代码片段

锁可以管理试图进入被保护代码段的线程

锁可以有一个或多个条件对象

条件对象管理那些已经进入被保护的代码段却不能执行的线程

volatile关键字

volatile关键字为实例域的同步访问提供一个免锁机制,那么编译器和虚拟机知道该字段可能被另一个线程并发更新。

final关键字

final保证其他线程在构造函数完成构造之后才能看到这个变量,而不是null。

导致死锁的情况

线程局部变量

ThreadLocal为各个线程提供各自的实例

final ThreadLocal<SimpleDateFormat> threadLocal = ThreadLocal.withInitial(() -> new SimpleDateFormat());
threadLocal.get().format(new Date());
原文地址:https://www.cnblogs.com/minguo/p/12393074.html