一.多线程
1.多线程介绍
(1)进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。
(2)线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程
~单线程程序:即,若有多个任务只能依次执行。当上一个任务执行结束后,下一个任务开始执行。
~多线程程序:即,若有多个任务可以同时执行。
2.程序运行原理
分时调度
所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
抢占式调度
优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。
3.主线程
jvm启动后,必然有一个执行路径(线程)从main方法开始的,一直执行到main方法结束,这个线程在java中称之为主线程。当程序的主线程执行时,如果遇到了循环而导致程序在指定位置停留时间过长,则无法马上执行下面的程序,需要等待循环结束后能够执行。
4.Thread类
自定义线程方式一:
1.继承Thread类
2.重写父类run方法,在run方法中写线程的执行代码
3.创建自定义线程类的对象
4.通过对象调用start(),启动线程,
开启线程并让线程执行,同时还会告诉jvm去调用run方法
获取线程名称:
1.String getName()
2.static Thread currentThread() 返回对当前正在执行的线程对象的引用。
链式调用: Thread.currentThread().getName()
设置线程名称:
1.构造方法设置:
类似自定义异常,需要调用父类带参(String)构造方法,所以需要在子类线程中添加带
参构造方法,并调用父类对应方法(加空参的构造)
2.void setName(String name) 改变线程名称,使之与参数 name 相同。
注:set方法设置名称,需要在线程对象创建之后,开启线程之前
5.创建线程方式—实现Runnable接口
创建线程的步骤。
1、定义类实现Runnable接口。
2、覆盖接口中的run方法。。
3、创建Thread类的对象
4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。
5、调用Thread类的start方法开启线程。
6.线程的匿名内部类使用
线程的匿名内部类使用
匿名内部类:
1.存在继承或实现关系,方法的重写
2.属于成员内部类:写在方法中
3.语法格式:
new 父类/接口(){
重写父类或接口方法
} =======相当于创建子类对象,可以调用方法属性
4.
(1)继承类或实现接口
(2)重写方法
(3)直接创建子类对象
(4)调方法或属性
方式1:创建线程对象时,直接重写Thread类中的run方法
new Thread() {
public void run() {
for (int x = 0; x < 40; x++) {
System.out.println(Thread.currentThread().getName()
+ "...X...." + x);
}
}
}.start();
方式2:使用匿名内部类的方式实现Runnable接口,重新Runnable接口中的run方法
Runnable r = new Runnable() {
public void run() {
for (int x = 0; x < 40; x++) {
System.out.println(Thread.currentThread().getName()
+ "...Y...." + x);
}
}
};
new Thread(r).start();
二.线程池
1.使用线程池方式–Runnable接口
Executors:线程池创建工厂类
- public static ExecutorService newFixedThreadPool(int nThreads):返回线程池对象
- ExecutorService:线程池类
- Future<?> submit(Runnable task):获取线程池中的某一个线程对象,并执行
- Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用
- 使用线程池中线程对象的步骤:
- 创建线程池对象
- 创建Runnable接口子类对象
- 提交Runnable接口子类对象
- 关闭线程池
public static void main(String[] args) {
//1.通过线程池工厂Executors,创建线程池ExecutorService(实现类)
ExecutorService ex = Executors.newFixedThreadPool(3);//创建容量为3的线程池
//2.创建Runnable接口子类对象
MyThread myThread = new MyThread();
//3.提交Runnable接口子类对象
ex.submit(myThread);
ex.submit(myThread);
ex.submit(myThread);
//4.关闭线程池
ex.shutdown();//一般不使用
}
2.使用线程池方式—Callable接口
Callable接口:与Runnable接口功能相似,用来指定线程的任务。其中的call()方法,用来返回线程任务执行完毕后的结果,call方法可抛出异常。
ExecutorService:线程池类
Future submit(Callable task):获取线程池中的某一个线程对象,并执行线程中的call()方法
Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用
使用线程池中线程对象的步骤:
创建线程池对象
创建Callable接口子类对象
提交Callable接口子类对象
关闭线程池
public static void main(String[] args) throws ExecutionException, InterruptedException {
//1.通过线程池工厂Executors,创建线程池ExecutorService(实现类)
ExecutorService ex = Executors.newFixedThreadPool(3);
//2.创建Callable接口子类对象
MyThreadCal mtc = new MyThreadCal();
//3.提交Callable接口子类对象
//结果为Future类型(Future接口实现类)
//调用FutureTask中的get方法可获取线程call方法的返回值
Future sub = ex.submit(mtc);
System.out.println(sub.get());
ex.submit(mtc);
ex.submit(mtc);
//4.关闭线程池
ex.shutdown();
}