一、概念
进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。如:QQ、微信、视频下载同时在使用。
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行。如:视频同时下载两个电影。
一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
如登录优酷后就是一个进程,里面下载两个电影,在线观看一部电视剧这就是三个线程。
二、程序运行原理
分时调度:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
抢占式调度:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个。
创建线程的目的:是为了建立程序单独的执行路径,让多部分代码实现同时执行。main函数中是主线程,自定义线程在定义在run方法中。如果只是run()方法就按照一条线程普通执行,多线程就可以同时执行。
三、Thread类
Thread是程序中的执行线程,Java 虚拟机允许应用程序并发地运行多个执行线程。
1.创建Thread子类
2.子类重写父类的方法
3.实例化子类对象
4.子类调用start()方法
Thread子类:
//定义SubThreadd继承Thread类
public class SubThreadd extends Thread{
//重写父类run()方法
public void run(){
//打印
for (int i = 0; i < 50; i++) {
System.out.println("Thread"+i);
}
}
}
测试类:
public class Test01 {
public static void main(String[] args) {
//创建Thread子类对象
SubThread s=new SubThread();
//调用start()方法
s.start();
}
}
内存中:在栈内存中,其实每一个执行线程都有一片自己所属的栈内存空间,进行方法的压栈和弹栈。
获得线程名称:
//获得主方法的线程名
System.out.println(Thread.currentThread().getName());
四、Runnable接口
1.写Runnable接口的实现类
2.重写run()方法
3.Main方法中创建Thread对象,将接口实现类对象传入
4.Thread对象调用start()方法
//定义SubRunnable继承Runnable接口
public class SubRunnable implements Runnable{
//实现类重写接口中的run()方法
public void run() {
//打印
for (int i = 0; i < 50; i++) {
System.out.println("Runnable"+i);
}
}
}
测试类:
public class Test01 {
public static void main(String[] args) {
//创建Runnable对象
SubRunnable sr=new SubRunnable();
//创建Thread对象,把Runnable对象传过来
Thread tr=new Thread(sr);
//调用start()方法
tr.start();
}
}
优点:实现Runnable接口,避免了继承Thread类的单继承局限性。覆盖Runnable接口中的run方法,将线程任务代码定义到run方法中。
共享问题:Runnable是共享的,里面的数据是共享访问的
五、线程池
线程池:是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。主要用来解决线程生命周期开销问题和资源不足问题。
线程池Runnable接口 :
//定义SubRunnable实现Runnable接口
public class SubRunnable implements Runnable{
public void run() {
System.out.println("nihao");
}
}
测试类:
/*
* 线程池Runnable接口
*/
public class Test01 {
public static void main(String[] args) {
//创建线程池对象
ExecutorService es=Executors.newFixedThreadPool(2);
//常见Runnable实例对象
SubRunnable sr=new SubRunnable();
//从线程池中获得线程对象,线程池控制线程关闭,用完之后又返回到线程池中
es.submit(sr);
es.submit(sr);
es.submit(sr);
//关闭线程池
es.shutdown();
}
}
线程池Callable接口:
//定义MyCallable实现Callable<E>接口
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Integer>{
int x=2, y=3;
public Integer call() throws Exception {
return 2*3;
}
}
测试类:
/*
* 线程池Callable接口
*/
public class Test02 {
public static void main(String[] args) throws Exception, ExecutionException {
//创建线程池对象
ExecutorService es=Executors.newFixedThreadPool(2);
//创建Runnable对象
MyCallable mc=new MyCallable();
//从线程池中获取线程对象
Future<Integer> fi=es.submit(mc);
//获得里面的内容
Integer i=fi.get();
System.out.println(i);
//关闭线程池
es.shutdown();
}
}
小结:
线程是为了提高效率,一个进程开启多个线程,在CPU中只可以有一个线程进行工作,但是因为CPU切换的速度很快,可以在多个线程之间进行高速切换,所以感觉是多个线程同时执行的。通过继承Thread类和实现Runnable接口都可以实现线程的应用。