Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。
多线程的使用
新建状态:
使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
就绪状态:
当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
运行状态:
如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
阻塞状态:
如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
死亡状态:
一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。
线程的优先级:Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。默认情况下,每一个线程都会分配一个优先级 NORM_PRIORITY(5)。
守护线程:守护线程又称后台线程,默认创建的线程都是普通线程或称为前台线程,线程提供了一个方法setDaemon(boolean on),只有调用该方法并传入参数为true时,该线程才会被设为守护线程。守护线程与普通线程的唯一区别是:当JVM中所有的线程都是守护线程的时候,JVM就可以退出了;如果还有一个或以上的非守护线程则不会退出。(以上是针对正常退出,调用System.exit则必定会退出)。
创建一个新的线程
继承Thread
public class MyThread extends Thread {
@Override
public void run() {
// 线程执行的任务
}
}
// 创建并启动线程
MyThread thread = new MyThread();
thread.start();
实现Runnable
public class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行的任务
}
}
// 创建并启动线程
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
通过 Callable 和 Future 创建线程,获取线程执行结果
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// 线程执行的任务,返回结果
return 1 + 2;
}
}
// 创建 Callable 对象和 FutureTask 对象
MyCallable callable = new MyCallable();
FutureTask<Integer> futureTask = new FutureTask<>(callable);
// 创建并启动线程
Thread thread = new Thread(futureTask);
thread.start();
// 获取 Callable 返回的结果,如果线程未执行完毕会阻塞
Integer result = futureTask.get();
/*---------------------CompletableFuture异步编程 多线程同时等待执行结果-------------------------*/
//创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
//开启异步任务1
CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {
System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId());
int result = 1 + 1;
System.out.println("异步任务1结束");
return result;
}, executorService);
//开启异步任务2
CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {
System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId());
int result = 1 + 2;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("异步任务2结束");
return result;
}, executorService);
//开启异步任务3
CompletableFuture<Integer> task3 = CompletableFuture.supplyAsync(() -> {
System.out.println("异步任务3,当前线程是:" + Thread.currentThread().getId());
int result = 1 + 3;
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("异步任务3结束");
return result;
}, executorService);
//任务组合
CompletableFuture<Void> allOf = CompletableFuture.allOf(task, task2, task3);
//等待所有任务完成
allOf.get();
//获取任务的返回结果
System.out.println("task结果为:" + task.get());
System.out.println("task2结果为:" + task2.get());
System.out.println("task3结果为:" + task3.get());
/*---------------------多线程同时等待执行结果-------------------------*/
spring中的多线程
filling...
多线程常用API与工具类
Object
notify() ,唤醒正在等待对象监视器的单个线程。
notifyAll() ,唤醒正在等待对象监视器的所有线程。
wait() ,导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
wait(long timeout) ,导致当前线程等待,直到另一个线程调用 notify()方法或该对象的 notifyAll()方法,或者指定的时间已过。
Thread
public Thread(String name) , 指定线程名称
public void start(),线程启动
public static Thread currentThread(),获取当前线程
public static void sleep(long time),线程休眠
setPriority(int newPriority)
,更改此线程的优先级public final void setDaemon(boolean on)
,将此线程标记为daemon线程或用户线程
TimeUnit,java.util.concurrent包下面的一个类,表示给定单元粒度的时间段