一、进程与线程
1.什么是程序
程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,可以理解为程序是包含静态代码的文件。例如:浏览器软件、音乐播放器软件等软件的安装目录和文件。
2.什么是进程
进程是程序的一次执行过程,是系统运行程序的基本单位。在 windows 系统中,每一个正在执行的 exe 文件或后台服务,都是一个进程由操作系统统一管理并分配资源,因此进程是动态的。例如:正在运行中的浏览器就是一个进程。
3.什么是线程
某些进程内部还需要同时执行多个子任务,我们把子任务称为线程。线程是进程划分成的更小的运行单位。
进程和线程的关系就是:一个进程可以包含一个或多个线程,但至少会有一个主线程。
4.进程与线程的区别
进程是是程序的一次执行过程,强调资源分配,而线程是进程划分成的更小的运行单位,强调执行过程。
一个进程内包含有多个线程,在执行过程,线程的执行不是线性串行的,而是多条线程并行共同完成。
二、线程的创建方式
线程的创建只有一种方式,通过Thread创建线程对象,但其对象实现方式有如下四种:
1.方式一:继承 java.lang.Thread 类(线程子类)
// 主线程main
public class MultiThread {
public static void main(String[] args) {
//创建并启动子线程
Thread t = new Thread(new SubThread());
t.start();
//主线程继续同时向下执行
for (int i = 0; i < 100; i++)
System.out.println("主线程" + i + " ");
}
}
// 线程执行类
class SubThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("子线程" + i + " ");
}
}
}
2.方式二:实现java.lang.Runnable接口(线程执行类)
// 主线程main
public class MultiThread {
public static void main(String[] args) {
//创建并启动子线程
Thread t = new Thread(new SubThread());
t.start();
//主线程继续同时向下执行
for (int i = 0; i < 100; i++)
System.out.println("主线程" + i + " ");
}
}
// 线程执行类
class SubThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("子线程" + i + " ");
}
}
}
3.方式三:实现java.util.concurrent.callable 接口,允许子线程返回结果、抛出异常
// 主线程main
public class MultiThread {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//子线程封装为FutureTask对象,计算1-100的累加和
SubThread subThread1 = new SubThread(1, 100);
FutureTask<Integer> task1 = new FutureTask<>(subThread1);
//子线程封装为FutureTask对象,计算101-200的累加和
SubThread subThread2 = new SubThread(101, 200);
FutureTask<Integer> task2 = new FutureTask<>(subThread2);
// 分别启动两个子线程
new Thread(task1).start();
new Thread(task2).start();
// 分别获取两个子线程的计算结果
int sum1 = task1.get();
int sum2 = task2.get();
// 汇总计算结果
int total = sum1 + sum2;
System.out.println(total);
}
}
// 实现子线程
class SubThread implements Callable<Integer> {
private int begin, end;
public SubThread(int begin, int end) {
this.begin = begin;
this.end = end;
}
@Override
public Integer call() throws Exception {
int result = 0;
for (int i = begin; i <= end; i++) {
result += i;
}
return result;
}
}
4.方式四:线程池
public class MultiThread {
public static void main(String[] args) {
// 创建固定大小的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(10);
while (true) {
//提交多个执行任务至线程池,并执行
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("当前运行的线程名为: " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
}
}
三、线程的优先级
在线程中,通过setPriority(int n)设置线程优先级,范围是1-10,默认为 5。
优先级高的线程被操作系统调度的优先级较高(操作系统对高优先级线程,调度更频繁)。
注意:并不能代表,通过设置优先级来确保高优先级的线程一定会先执行。
四、总结
- Java用 Thread 对象表示一个线程,通过调用 start()启动一个新线程
- 一个线程对象只能调用一次 start()方法;
- 线程的执行代码写在 run()方法中
- 线程调度由操作系统决定,程序本身无法决定调度顺序,
- Thread.sleep()可以把当前线程暂停一段时间。