线程:是进程中的一个执行场景,也就是执行流程
启动一个进程相当于启动一个应用程序
进程和进程之间的内存是独立的
一个进程可以启用多个线程
单进程:只能做一件事
多线程:为了提高应用程序的使用率
例:人可以用电脑边玩游戏边听音乐,给人感觉玩游戏和听音乐是在同一时间点进行,其实不是,只是游戏进程和音乐进程频繁切换得很快,给人的一种错觉
Java程序的运行原理:
Java命令会启动Java虚拟机,等于启动一个应用程序,也就是启动一个进程,该进程会自动启动一个主线程,这个主线程会自动调用某个类的main方法
线程的创建和启动:
1.继承Thread类 ( java.lang )
1) 定义线程,继承线程Thread类并重写run方法
2) 创建线程
3) 启动线程
2.实现Runable接口
1) 定义线程,继承线程Runable类并重写run方法
2) 创建线程
3) 启动线程
线程的调度与控制
分时调度模型:所有线程轮流使用cpu的使用权,使用时间相等
抢占式调度模型(Java使用的是抢占式调度模型)
线程的优先级
线程的优先级高,那个线程拿到CPU的使用权机率大
setName():改变线程的名字
线程的同步(加锁)
异步线程模型
t1,t2线程,两个线程运行时互不影响
同步线程模型
t1线程 必须等到 t2线程 运行结束后才能执行
最主要是考虑线程的安全 [ 数据的安全(共享数据的安全) ]
面试题:
使用Thread类和实现runable接口的异同点:
例:
1 package hello1;
2
3 //定义一个线程 继承Thread类
4 public class ThreadA extends Thread{
5 //重写run()方法
6 @Override
7 public void run(){
8 for(int i=0;i<20;i++){
9 System.out.println("ThreadA..run.."+i);
10 }
11 }
12 }
1 package hello1;
2
3 //重写的方法不能抛出比原方法所抛出的异常类型更宽泛
4 //实现runable接口
5 public class ThreadB implements Runable{
6 @Override
7 public void run(){
8 Thread t=Thread.currentThread();
9 for(int i=0;i<10;i++){12
13 / * try{
14 Thread.sleep(1000);
15 }catch(InterruptedException e){
16 e.printStackTrace();
17 } * /
18 System.out.println(""+t.getName()+"..."+i);
19 }
20 }
21}
1 package hello1;
2 public classTestMAin{
3 public static void main(String[] ages){
4 //创建线程
5 Thread t=new ThreadA();
6 Thread t1=new Thread(new ThreadB());
7 //setName():改变线程的名字
8 t1.setName("t1");
9
10 //setPriority():改变线程优先级;设置t1线程的优先级最高
11 t1.setPriority(10);
12
13 //启动线程(调用start()方法时,会自动调用run()方法)
14 t.start(); //结果不定,用到多线程,在t线程中运行
15 t1.start();
16 //t.run(); //结果:先run后main;只是一个普通方法的调用,没有用到多线程
17
18 System.out.println("最高优先级:"+Thread.MAX_PRIORITY);
19 System.out.println("默认优先级:"+Thread.NORM_PRIORITY);
20 System.out.println("最低优先级:"+Thread.MIN_PRIORITY);
21
22 //这段代码是在主线程运行的
23 /*
24 for(int i=0;i<10;i++){
25 System.out.println("TestMain..ThreadA..main.." + i);
26 }
27
28 for(int i=0;i<10;i++){
29 System.out.println("TestMain..ThreadB..main.." + i);
30 }
31 */
32 }
34 }
输出结果:
因为设置了“ t1.setPriority(10); ”,所以ThreadB..比ThreadA..先输出
但如果设置“ Thread.sleep(1000); ”,即ThreadB延迟1000毫秒输出,这个就跟线程的状态有关了,你设置了sleep就等于将当前线程挂起1000MS,这个跟线程优先级无关,当时间到了以后,再执行。
而只设置优先级的话,那等于是t1和t2线程只要产生冲突,那么被挂起的永远是优先级低的那个。只要你其中的一个线程睡眠,他就会执行另一个,因此会交替出现
1000MS=1s(1000毫秒=1秒)
小知识点:
类是单继承,默认是包可访问,方法默认是可以覆盖(Override)的,static,final,abstract等修饰语的含义也很清晰。