任务管理器可以有多个进程,每个进程运行的都是可执行程序,一个可执行程序就是一个软件,可执行程序的本质就是在计算机当中运行的一块代码
进程:可以看成是在计算机当中运行的一块代码
线程:可以看成是在计算机当中运行的一小块代码
线程与进程的关系
- 一个进程中可以有多个线程,至少得有一个线程;
- 上面说一个进程可以狭隘的看成是一大段代码,那其实线程也是一段代码
- 线程是进程中的最小单位;
- 也可以把线程看成是一个轻量级的进程
注意常识 : 计算机安装一个软件,软件是由代码构成,当启动一个软件之后,代码被放入内存中,为什么会放入到内存中,因为内存的读写速度比较快,这时候CPU就开始处理内存当中的任务,也就是当前软件程序[ 代码 ]运行起来了
线程的作用
- 线程的作用:看下面两种理解方式:
①可以将代码中(软件)的某些独立的功能包装起来,单独作为任务交给CPU处理!
②将需做的某个功能封装成一个线程体,该线程可以独立的获得CPU分配的资源
从而实现多功能同时运行
创建启动线程的方式一(继承Thread类)
先明确我们需要把什么事情封装成一个线程对象(现有相应的代码)
自定义一个类 extends Thread
覆写run方法,在这里写1步中的代码
创建一个自定义类的对象 t
启动线程 t.start();
注意执行过程:本质是代码执行到一个位置之后,如果切换到另一个线程,在切换回来,那么会从刚才切换走的代码位置继续执行:产生线程安全问题的原因,就在此...
直接调用run方法和start的区别?
可以直接调用run方法,但是没有启动一个独立的线程;
只有调用start 才回启动一个独立的线程;
自己启动的线程和主线程有关系吗?
直接写一个最简单的hello word 程序,就有一个主线程
一个线程一旦启动就是独立的了,和创建启动它的环境没有直接的包含关系
线程的创建启动方式二
Thread线程类本质是实现Runnable接口
自定义类通过实现Runable的方式来实现线程,如何启动
小结:实现方式启动线程的流程
- 明确线程主体(自己需要实现的代码);
- 自定义一个类实现Runnable接口
- 覆写run方法 : 写第一步中的代码
- 创建一个自定义类的对象 t
- 以t为参数来构造一个Thread对象 tt;
Thread tt = new Thread(tt);
tt.start();//启动线程对象tt,对线程对象t 的主体代码进行访问
继承Thread 和实现Runnable的区别
- 继承有局限,Java中类只能够单继承
- 实现的方式,我们的类在业务上可以继承它本应该有的类,同时可以实现接口变成一个线程类
关于数据共享的问题:就看所谓被共享的数据所在的类的对象被创建了几个
线程休眠sleep
线程类Thread当中有一个static void sleep(long millis)方法,在指定的毫秒数内让当前正在执行的线程休眠
线程优先级
每个线程[线程对象]都有一个优先级,高优先级线程的执行优先于低优先级线程(简单说:如果一个线程的优先级越高,获得CPU资源的机会更大,不等于高优先级的就最先执行)
如何设置优先级
int getPriority() 返回线程的优先级
void setPriority(int newPriority) 更改线程的优先级
等待线程终止join()
join为线程当中的方法,某线程实例调用该方法,其他线程会等待该线程执行完毕之后在执行
为什么需要线程同步
- 解决问题: 线程安全问题
(例如1单例模式的懒汉模式;例如2多线程模拟多窗口售票-)
线程同步方式一:同步代码
2.2.1基本语法结构
synchronized (同步监听对象) {
可能引发线程安全问题的代码
}
上面的结构相当于把{ }中的代码捆绑成一个整体,线程只能够一个一个的进来,执行完一个,下一个才能进来
2.2.2语法特点:
上面的同步监听对象可以是任意的对象;
保证所有的线程共享一个同步监听对象的;也就是保证被同步监听对象是被所有线程共享的。
很多时候可以写this,但是请先参照②,
常用的方式:使用类的字节码对象 XXX.class
线程同步方式二:同步方法
就是在需要被同步的方法上面加关键字 synchronized
加的位置 :在返回值类型的前面
不需要也不能够显示的写同步监听对象
如果是一个非static的方法,那么同步监听对象就是this;
如果是static修饰的方法,那么同步监听对象就是当前方法所在的类的字节码对象
线程同步方式三:锁机制
学习方式(查找API文档方式)锁-- Lock(API)接口 ---XXX实现类