线程基础
- 程序、进程、线程?
-
程序:
程序是含有指令和代码的文件,被存储在磁盘或其他数据存储设备中,可以理解为程序是包含静态代码的文件。例如,浏览器软件,游戏软件等软件的安装目录和文件
-
进程:
进程是程序的一次执行过程,是系统运行程序的基本单位,并分配CPU、网络、磁盘、内存等资源
-
线程:
线程是进程划分成的更小的运行单位。进程和线程的关系:一个进程可以包含一个或多个线程,但至少会有一个主线程。
线程的创建
创建Thread对象
Thread thread = new Thread();
线程的实现
-
实现Runnable接口
Thread thread = new Thread(new Runnable() {@Overridepublic void run() {for(char c = 'a' ; c<='z' ; c++) {System.out.println(Thread.currentThread().getName() + " :" +c);}} },"子线程1"); thread.start(); // 启动子线程,自动执行Runnable接口的实现类对象的run()
-
继承Thread类
Thread thread2 = new Thread("子线程2") {@Overridepublic void run() {for(int i =1 ; i<=26 ; i++) {System.out.println(Thread.currentThread().getName() + " :" + i);}} }; // 启动子线程 thread2.start();
-
实现Callable接口(子程序执行后有返回值)
泛型:返回值类型
public static void main(String[] args) throws InterruptedException, ExecutionException {// 多线程实现1-10000相加SubTask subTask1 = new SubTask();FutureTask<Integer> futureTask1 = new FutureTask<Integer>(subTask1);// 创建线程对象Thread thread1 = new Thread(futureTask1);// 启动子线程thread1.start();// 当所有的子线程执行结束后,通过get方法获取返回值Integer sum1 = futureTask1.get();System.out.println(sum1); }class SubTask implements Callable<Integer> {@Overridepublic Integer call() throws Exception {int sum = 0;// xxxreturn sum;} }
-
线程池(提高线程的使用效率)
ExecutorService:Java中的一个接口,它提供了一种管理和执行线程的机制;
Executors:工具类,用于创建各种形式(类型)的线程池
Executors.newFixedThreadPool(n):创建n个线程数目的线程池
// 通过工具类创建5个线程的线程池 ExecutorService executorService = Executors.newFixedThreadPool(5);// 创建动态数目(数目不固定)的线程池 ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
线程池相关的方法:
-
线程池分配一个空闲线程执行任务的方法:submit();
-
关闭线程池的方法:shutdown();
-
线程的方法
-
获取当前JVM中的线程
public static void main(String[] args) {// 获取当前JVM中的进程ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);for(ThreadInfo threadInfo :threadInfos) {System.out.println("【"+threadInfo.getThreadId() +"】:"+ threadInfo.getThreadName());} }
-
获取当前线程:Thread.currentThread()
Thread.currentThread();
-
线程命名
Thread thread = new Thread(new Runnable{@Overridepublic void run() {xxx} },"xxx1"); // 给thread线程命名为xxx1Thread thread2 = new Thread("xxx2"){ // 给thread线程命名为xxx2@Overridepublic void run() {xxx} }Thread thread3 = new Thread(); thread3.setName("xxx3"); // 给thread3线程命名为xxx3
-
线程休眠:Thread.Sleep();
Thread.Sleep(1000); // 设置线程休眠1000毫秒
-
设置线程优先级
Thread对象.setPriority();优先级最高为10,最低为1,默认值为5
Thread thread1 = new Thread(); Thread thread2 = new Thread();thread1.setPriority(1); thread2.setPriority(10);
优先级只是起参考作用,设置高优先级不一定先完成任务
-
线程的插队
Thread对象.join();
join()方法通过wait()实现,是被插队的线程(主线程),处于等待状态。
public class thread05 {public static void main(String[] args) MyTask myTask = new MyTask();Thread thread = new Thread(myTask,"子线程1");thread.start();// 子线程的插队// 主线程不会等待子线程执行完毕再向下执行,主线程等待子线程执行完毕需要子线程插队try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("main线程执行完毕!"); }class MyTask implements Runnable{@Overridepublic void run() {char c = '一';for(int i = 0;i<26; i++,c ++ ) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+c);}} }
-
线程的中断
Thread对象.interrupt():设置当前线程为中断状态;
线程中断时,会抛出InterruptedException异常;
Thread对象.isInterrupted():判断当前线程是否为中断状态,返回值为Boolean类型
Thread thread = new Thread(); System.out.println(thread.isInterrupted()); // true OR false
-
线程的让出
线程调度模型:
- 分时调度模型:所有线程轮流获取CPU使用权,平均分配每个线程占用的CPU时间片
- 抢占调度模型:优先分配给优先级较高的线程占用CPU,如果优先级相同,则随机选择一个线程;JVM虚拟机采用抢占调度模型;
Thread.yield();
-
线程的分类
-
用户线程:所有用户线程执行结束后,JVM虚拟机会自动退出;
-
守护线程:守护线程执行结束后,JVM虚拟机不会自动退出;
Thread对象.setDaemon(true);
Thread thread = new Thread(); thread.setDaemon(true);
-
线程的状态
NEW、RUNNABLE、BLOCKED、WAITING、TIME_WAITING、TERMINATED
-
NEW:新建状态
调用构造方法后,线程处于新建状态;
-
RUNNABLE:可运行状态
调用线程的start()方法后,线程处于可运行状态;
-
BLOCKED:阻塞状态
两个线程同时竞争synchronized锁时,获取锁的线程处于RUNNABLE运行状态,未获取锁的线程处于BLOCKED阻塞状态;
-
WAITING:等待状态
必须通过notify()或notifyAll()唤醒
-
TIME_WAITING:计时等待状态
等待计时结束时,自动唤醒
-
TERMINTED:终止状态
线程任务执行完毕