多线程简介
1.Process与Thread
- 程序本身是指定和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
- 而进程则是执行程序中的一次执行过程,是一个动态的概念。是系统能够资源分配的单位。
- 通常在一个进程里,可以包含若干个线程,当然一个进程至少有一个线程,不然没有存在的意义。
- 线程是CPU调度和执行的单位,线程是独立的执行路径
注:很多的多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果模拟出来的多线程,即在一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为切换的很快,所有就有同时执行的错觉
- 在程序运行时,及时没有为自己创建线程,后台也会有多个线程,如主线程,gc线程等。
- main()称为主线程,为系统的入口,用于执行整个程序
- 在一个线程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为的干预的。
- 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制。
- 线程会带来额外的开销,如cpu调度时间,并发控制开销
- 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
- 对现在的程序来说至少需要两个线程,一个是执行main方法的主线程,一个垃圾回收(gc)线程.
2.线程的创建
我们现在一共有三种方式创建线程,分别是继承Threa类,
2.1通过继承Thread类创建
- //创建方式一:继承Thread类,重写run()方法,调用start开启线程
- package com.thread;
- public class ThreadTest01 {
- public static void main(String[] args) {
- MyThread01 myThread01 = new MyThread01();
- myThread01.start();
- //start()方法的作用是:启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码在任务完成之后,瞬间就结束了
- //这段代码的任务只是为了开启一个新的栈空间,只要新的栈空间开出来,start ()方法就结束了,线程就启动成功了
- //启动成功的线程会自动调用run方法,并且run方法在分支线的栈底部(压线)
- //run()方法在分支栈的栈底部,man方法在主栈的栈底部,run和main是平级的
- //muThread01.run;不会启动线程,不会分配新的分支线(这就是单线程)
- for (int i = 0; i < 100; i++) {
- System.out.println("主线程"+i);
- }
- }
- static class MyThread01 extends Thread{
- @Override
- public void run() {
- //编写程序,这段程序运行在分支线程中
- for (int i = 0; i < 100; i++) {
- System.out.println("分支线程"+i);
- }
- }
- }
复制代码 输出:因为输出较多,我们截取一部分,可以看出,是交替执行的。- 主线程8
- 分支线程68
- 分支线程69
- 主线程9
- 分支线程70
- 分支线程71
- 分支线程72
- 分支线程73
- 分支线程74
- 分支线程75
- 分支线程76
- 主线程10
- 分支线程77
- 主线程11
- 分支线程78
- 主线程12
- 分支线程79
- 主线程13
- 分支线程80
- 主线程14
- 分支线程81
- 主线程15
- 主线程16
- 分支线程82
- 主线程17
复制代码 线程开启不一定立即执行,是由cpu安排调度的
2.2编写一个类实现java.lang.Runnable接口
代码示例:- public class ThreadTest03 {
- public static void main(String[] args) {
- //创建线程对象
- Thread t = new Thread(new MyRunnable());
- //启动线程
- t.start();
- for (int i = 0; i < 100; i++) {
- System.out.println("主线程"+i);
- }
- }
- //这并不是一个线程类,是一个可运行的类,还不是一个线程
- static class MyRunnable implements Runnable{
- @Override
- public void run() {
- for (int i = 0; i < 100; i++) {
- System.out.println("分支线程"+i);
- }
- }
- }
- }
复制代码 部分输出结果:- 分支线程31
- 分支线程32
- 主线程45
- 主线程46
- 主线程47
- 主线程48
- 主线程49
- 主线程50
- 主线程51
- 主线程52
- 主线程53
- 主线程54
- 主线程55
- 主线程56
- 主线程57
- 主线程58
- 主线程59
- 主线程60
- 主线程61
- 分支线程33
- 分支线程34
- 分支线程35
- 分支线程36
- 分支线程37
- 分支线程38
- 分支线程39
复制代码 注:第二种方式实现接口比较常见,因为一个类实现了皆可以,还可以去继承其它的类,更加灵活!
3.多线程并发
- 进程与进程之间的内存独立不共享
- 在一个进程中,线程和线程的堆内存和方法区内存共享。但是栈内存独立,一个线程一个栈
假设启动十个线程,就会有十个栈空间,每个栈与每个栈之间,互不干扰,各自执行,这就是多线程并发
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |