进程是操作系统中的一个独立执行单元,它包含了程序代码、数据和系统资源的副本。每个进程都有自己的地址空间,它们之间通常是相互隔离的。
线程是进程内的一个执行单元,多个线程共享同一个进程的地址空间和资源。一个进程可以包含多个线程。
进程是程序运行资源分配(内存)的最小单位;线程是CPU调度的最小单位。
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:
*
* - {@link Object#wait() Object.wait} with no timeout
* - {@link #join() Thread.join} with no timeout
* - {@link LockSupport#park() LockSupport.park}
*
*
* A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called Object.wait()
* on an object is waiting for another thread to call
* Object.notify() or Object.notifyAll() on
* that object. A thread that has called 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:
*
* - {@link #sleep Thread.sleep}
* - {@link Object#wait(long) Object.wait} with timeout
* - {@link #join(long) Thread.join} with timeout
* - {@link LockSupport#parkNanos LockSupport.parkNanos}
* - {@link LockSupport#parkUntil LockSupport.parkUntil}
*
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
新建状态:
使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
就绪状态:
当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
运行状态:
如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
阻塞状态:
如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
死亡状态:
一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。
Java 提供了四种创建线程的方法:
show me the code!
package com.junfeng.manage.test;
public class MyThread extends Thread {
public static void main(String[] args) {
System.out.println("main----start");
MyThread thread01 = new MyThread();
thread01.start();
System.out.println("main----stop");
}
@Override
public void run() {
System.out.println("junfeng");
}
}
package com.junfeng.manage.test;
public class RunnableTest implements Runnable{
public static void main(String[] args) {
System.out.println("main----start");
new Thread(new RunnableTest()).start();
System.out.println("main----stop");
}
@Override
public void run() {
System.out.println("hello,junfeng~");
}
}
package com.junfeng.manage.test;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MyCallable implements Callable<String > {
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main----start");
FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
new Thread(futureTask).start();
System.out.println(futureTask.get());
System.out.println("main----stop");
}
@Override
public String call() throws Exception {
return "hello,junfeng~";
}
}
package com.junfeng.manage.test;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolTest {
static ExecutorService service = Executors.newFixedThreadPool(2);//实例创建的为使用的固定线程的线程池
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main----start");
//传入一个Runable对象
service.execute(new MyRunnable());
//关闭线程池
service.shutdown();
System.out.println("main----stop");
}
}
假如有3个线程(A,B,C),怎么让它们按照指定的顺序执行任务呢?假设希望按照 A->B->C 的顺序执行。
利用Semaphore、CountDownLatch、CyclicBarrier 当成信号变量,作顺序开关。这里只写Semaphore代码,CountDownLatch、CyclicBarrier是类似的。注意:这里需要两个信号通知,因此需要定义两个Semaphore。
@Slf4j
public class Test {
/**
* Semaphore 信号量实现
* {@link Semaphore}
*/
public static void main(String[] args) {
// 3个线程需要2两个信号量,A->B需要一个,B->C需要一个
Semaphore signalAB = new Semaphore(0);
Semaphore signalBC = new Semaphore(0);
A a = new A(signalAB);
B b = new B(signalAB, signalBC);
C c = new C(signalBC);
// 线程池中 按顺序执行 A->B->C
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(b);
executorService.execute(c);
executorService.execute(a);
// 停止接受新任务,当已有任务将执行完,关闭线程池
executorService.shutdown();
while (!executorService.isTerminated()) {
// 等待所有线程执行完成
}
System.out.println("over");
System.exit(0);
}
@AllArgsConstructor
static class A implements Runnable {
private Semaphore semaphoreAB;
@SneakyThrows
@Override
public void run() {
log.info("A");
semaphoreAB.release();
}
}
@AllArgsConstructor
static class B implements Runnable {
private Semaphore semaphoreAB;
private Semaphore semaphoreBC;
@SneakyThrows
@Override
public void run() {
// semaphore 信号量-1,总数为0的时候会等待
semaphoreAB.acquire();
log.info("B");
// semaphore 信号量+1
semaphoreBC.release();
}
}
@AllArgsConstructor
static class C implements Runnable {
private Semaphore semaphoreBC;
@SneakyThrows
@Override
public void run() {
semaphoreBC.acquire();
log.info("C");
}
}
}
@Slf4j
public class ThreadABC {
/**
* CompletableFuture (推荐)
* JDK1.8中 CompletableFuture提供了非常强大的Future的扩展功能,简化异步编程,
* 提供函数式编程的能力,可帮助我们完成复杂的线程的阶段行编程(CompletionStage)
* {@link java.util.concurrent.CompletableFuture}
*/
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
// 有a,b,c三个线程(任务)
Runnable a = () -> log.info("A");
Runnable b = () -> log.info("B");
Runnable c = () -> log.info("C");
// 异步执行
CompletableFuture.runAsync(a, executorService).thenRun(b).thenRun(c);
log.info("main thread.");
// 停止接受新任务,当已有任务将执行完,关闭线程池
executorService.shutdown();
while (!executorService.isTerminated()) {
// 等待所有线程执行完成
}
System.exit(0);
}
}
守护线程也就是“后台线程”,一般用来执行后台任务,守护线程最典型的应用就是GC(垃圾回收器)。
唯一的区别就是Java虚拟机在所有<用户线程>都结束后就会退出,而不会等<守护线程>执行完。