JUC并发编程
JUC概述
JUC是java.util.concurrent包的简称,即Java并发编程工具包,目的是为了更好地支持高并发任务,让开发者进行多线程编程时有效减少竞争条件和死锁线程。
并发编程
一些基本概念:
进程与线程:
- 进程:程序是静止的,进程实体的运行过程就是进程,是系统进行资源分配的基本单位
- 线程:线程是属于进程的,是一个基本的 CPU 执行单元,是程序执行流的最小单元。线程是进程中的一个实体,是系统独立调度的基本单位,线程本身不拥有系统资源,只拥有一点在运行中必不可少的资源,与同属一个进程的其他线程共享进程所拥有的全部资源
并发与并行:
- 并行:在同一时刻,有多个指令在多个 CPU 上同时执行
- 并发:在同一时刻,有多个指令在单个 CPU 上交替执行
同步与异步:
- 需要等待结果返回,才能继续运行就是同步
- 不需要等待结果返回,就能继续运行就是异步
进程间通信:
- 信号量
- 共享 存储
- 管道通信
- 消息队列
Java中的通信机制:volatile、等待/通知机制、join 方式、InheritableThreadLocal、MappedByteBuffer
线程状态:
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW, 新建
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE, 准备就绪
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,阻塞
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called {@code Object.wait()}
* on an object is waiting for another thread to call
* {@code Object.notify()} or {@code Object.notifyAll()} on
* that object. A thread that has called {@code Thread.join()}
* is waiting for a specified thread to terminate.
*/
WAITING,等待
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,有时限的等待
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;终止
}
线程
线程创建的三种方式
第一种方式:
启动线程调用start方法,如果直接调用run,就变成普通的启动了
public class ThreadDemo01 {
public static void main(String[] args) {
Thread myThread = new MyThread();
myThread.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread()+":"+i);
}
}
}
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread()+":"+i);
}
}
}
第二种方式:
public class ThreadDemo02 {
public static void main(String[] args) {
Runnable target = new MyThread02();
Thread thread = new Thread(target,"线程1");
thread.start();
thread.run();
}
}
class MyThread02 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//Thread.currentThread()获取当前线程
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
第三种方式:
public class ThreadDemo03 {
public static void main(String[] args) {
Callable call = new MyCallable();
FutureTask<String> task = new FutureTask<>(call);
Thread t = new Thread(task);
t.start();
try {
String s = task.get(); // 获取call方法返回的结果(正常/异常结果)
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return Thread.currentThread().getName() + "->" + "Hello World";
}
}
线程状 态的转换
-
线程创建之后调用start()方法开始运行,当调用wait(),join(),LockSupport.lock()方法线程会进入到WAITING状态,
-
而同样的wait(long timeout),sleep(long),join(long),LockSupport.parkNanos(),LockSupport.parkUtil()增加了超时等待的功能,也就是调用这些方法后线程会进入TIMED_WAITING状态,
-
当超时等待时间到达后,线程会切换到Runable的状态,
-
另外当WAITING和TIMED _WAITING状态时可以通过Object.notify(),Object.notifyAll()方法使线程转换到Runable状态。
-
当线程出现资源竞争时,即等待获取锁的时候,线程会进入到BLOCKED阻塞状态,当线程获取锁时,线程进入到Runable状态。
-
线程运行结束后,线程进入到TERMINATED状态
线程的基本操作
yield与sleep
yield作用:提出释放CPU时间片的请求。不会释放锁,线程依然处于RUNNABLE状态。
sleep作用:会让当前线程从 Running 进入 Timed Waiting 状态(阻塞),不会释放对象锁
所以
yield()
方法调用后线程只是暂时的将调度权让给别人,但立刻可以回到竞争线程锁的状态;而sleep()
方法调用后线程处于阻塞状态。