进程和线程
进程
进程:进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位。也就是程序的执行过程。
- 独立性:每一个进程都有自己的空间,在没有经过进程本身允许的情况下,一个进程不可以直接访问其它的的进程空间。
- 动态性:进程是动态产生,动态消亡的
- 并发性:任何进程都可以同其它进程一起并发执行
并行和并发
并行:在同一时刻,有多个指令在多个CPU上【同时】执行
并发:在同一时刻,有多个指令在单个CPU上【交替】执行
多进程同时工作:
对于CPU而言,它是多个进程间轮换执行的
线程
线程:进程可以执行多个任务,每个任务就是线程
多线程的意义:
- 随着处理器的核心数量越来越多,现在大多数计算机都比以往更加擅长并行计算。
- 一个线程,在一个时刻,只能运行在一个处理器核心上。
- 提高执行效率。
- 同时处理多个任务。
Java默认是多线程
public class ThreadDemo {
/*
Java程序默认是多线程的, 程序启动后默认会存在两条线程
1. 主线程
2. 垃圾回收线程
*/
public static void main(String[] args) {
Thread mt = new Thread();
mt.start();
for (int i = 1; i <= 2000; i++) {
System.out.println("main线程执行了");
}
// 制造垃圾
for (int i = 1; i <= 500000; i++) {
new Demo();
}
}
}
class Demo {
@Override
protected void finalize() throws Throwable {
System.out.println("垃圾被清理了");
}
}
Java开启线程的方式
继承Thread类
public class ThreadDemo1 {
/*
开启线程第一种方式: 继承Thread类
1. 编写一个类继承Thread
2. 重写run方法
3. 将线程任务代码写在run方法中
4. 创建线程对象
5. 调用start方法开启线程
细节: 调用start方法开启线程, 会自动的调用run方法执行.
注意: 只有调用了start方法, 才是开启了新的线程
*/
public static void main(String[] args) {
// 4. 创建线程对象
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
// 5. 调用start方法开启线程
mt1.start();
mt2.start();
}
}
// 1. 编写一个类继承Thread
class MyThread extends Thread {
// 2. 重写run方法
@Override
public void run() {
// 3. 将线程任务代码写在run方法中
for (int i = 1; i <= 200; i++) {
System.out.println("线程任务执行了" + i);
}
}
}
实现Runnable接口
public class ThreadDemo2 {
/*
开启线程的第二种方式: 实现Runnable接口
1. 编写一个类实现Runnable接口
2. 重写run方法
3. 将线程任务代码写在run方法中
4. 创建线程任务资源
5. 创建线程对象, 将资源传入
6. 使用线程对象调用start方法, 开启线程
*/
public static void main(String[] args) {
// 4. 创建线程任务资源
MyRunnable mr = new MyRunnable();
// 5. 创建线程对象, 将资源传入
Thread t = new Thread(mr);
// 6. 使用线程对象调用start方法, 开启线程
t.start();
for (int i = 1; i <= 2000; i++) {
System.out.println("main线程执行了");
}
}
}
// 1. 编写一个类实现Runnable接口
class MyRunnable implements Runnable {
// 2. 重写run方法
@Override
public void run() {
// 3. 将线程任务代码写在run方法中
for (int i = 1; i <= 200; i++) {
System.out.println("线程任务执行了" + i);
}
}
}
实现Callable接口(线程执行完如果有结果产生,并且需要返回值)
public class ThreadDemo3 {
/*
开启线程的第三种方式: 实现Callable接口
1. 编写一个类实现Callable接口
2. 重写call方法
3. 将线程任务代码写在call方法中
4. 创建线程任务资源对象
5. 创建线程任务对象, 封装线程资源
6. 创建线程对象, 传入线程任务
7. 使用线程对象调用start开启线程
*/
public static void main(String[] args) throws Exception {
// 创建线程任务资源对象
MyCallable mc = new MyCallable();
// 创建线程任务对象, 封装线程资源
FutureTask<Integer> task1 = new FutureTask<>(mc);
FutureTask<Integer> task2 = new FutureTask<>(mc);
// 创建线程对象, 传入线程任务
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
// 使用线程对象调用start开启线程
t1.start();
t2.start();
Integer result1 = task1.get();
Integer result2 = task2.get();
System.out.println("task1获取到的结果为:" + result1);
System.out.println("task2获取到的结果为:" + result2);
}
}
// 1. 编写一个类实现Callable接口
class MyCallable implements Callable<Integer> {
// 2. 重写call方法
@Override
public Integer call() throws Exception {
// 3. 将线程任务代码写在call方法中
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
System.out.println("sum=" + sum);
}
return sum;
}
}
线程相关方法
方法名称 | 说明 |
---|---|
String getName() | 返回此线程的名称 |
void setName(String name) | 设置线程的名字(构造方法也可以设置名字) |
static Thread currentThread() | 获取当前线程的对象 |
static void sleep(long time) | 让线程休眠指定的时间,单位为毫秒 |
setPriority(int newPriority) | 设置线程的优先级 |
final int getPriority() | 获取线程的优先级 |
final void setDaemon(boolean on) | 设置为守护线程 |
与线程名有关的方法
String getName() | 返回此线程的名称 |
---|---|
void setName(String name) | 设置线程的名字(构造方法也可以设置名字) |
**static **Thread currentThread() | 获取当前线程的对象 |
public class ThreadMethodDemo01 {
/**
* 开启线程第一种方式:继承Thread类
* 1.编写一个类继承Thread
* 2.重写run方法
* 3.将线程任务代码写在run方法中
* 4.创建线程对象
* 5.调用start方法开启线程
* 细节:调用start方法开启线程,会自动调用run方法执行
* <p>
* Thread类的方法:
* public String getName():获取线程名字
* public void setName():设置线程名字
* public static Thread currentThread():获取当前线程的对象
*/
public static void main(String[] args) {
// 4.创建线程对象
MyThread1 myThread11 = new MyThread1("A:");
MyThread1 myThread12 = new MyThread1("B:");
// myThread11.setName("Cammy:");
// myThread12.setName("Lee:");
// 5.调用start方法开启线程
myThread11.start();
myThread12.start();
}
}
// 1.编写一个类继承Thread
class MyThread1 extends Thread {
public MyThread1() {
}
public MyThread1(String name) {
super(name);
}
// 2.重写run方法
@Override
public void run() {
// 3.将线程任务代码写在run方法中
for (int i = 0; i <= 200; i++) {
System.out.println(super.getName() + " 线程任务执行了 " + i);
}
}
}
public class ThreadMethodDemo02 {
/*
开启线程的第二种方式:实现Runnable接口
1.编写一个类实现Runnable接口
2.重写run
3.将线程任务方法写在run方法中
4.创建线程任务资源
5.创建线程对象,将资源传入
6.使用线程对象调用start,开启线程
*/
public static void main(String[] args) {
// 4.创建线程任务资源
MyRunnable1 myRunnable = new MyRunnable1();
// 5.创建线程对象,将资源传入
Thread t = new Thread(myRunnable, "线程A:");
// 6.使用线程对象调用start,开启线程
t.start();
for (int i = 0; i <= 2000; i++) {
System.out.println(Thread.currentThread().getName() + "线程被执行了");
}
}
}
// 1.编写一个类实现Runnable接口
class MyRunnable1 implements Runnable {
// 2.重写run
@Override
public void run() {
// 3.将线程任务方法写在run方法中
int sum = 0;
for (int i = 0; i <= 200; i++) {
sum += i;
System.out.println(Thread.currentThread().getName() + "线程任务执行了" + i);
}
}
}
public class ThreadMethodDemo03 {
/*
开启线程的第三种方式,实现Callable接口
1.编写一个类实现Callable接口
2.重写call方法
3.将线程任务代码写在call方法中
4.创建线程任务资源对象
5.创建线程任务对象,封装线程资源
6.创建线程对象,传入线程任务
7.使用线程对象调用start开启线程
*/
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建线程任务资源对象
MyCallable1 myCallable = new MyCallable1();
// 创建线程任务对象,封装线程资源
FutureTask<Integer> task = new FutureTask<>(myCallable);
FutureTask<Integer> task1 = new FutureTask<>(myCallable);
// 创建线程对象,传入线程任务
Thread thread = new Thread(task, "线程A:");
Thread thread1 = new Thread(task1, "线程B:");
// 使用线程对象调用start开启线程
thread.start();
thread1.start();
// 线程开起来了才能拿到结果
Integer result = task.get();
Integer result1 = task1.get();
System.out.println(thread.getName() + "获取到的结果为:" + result);
System.out.println(thread1.getName() + "获取到的结果为:" + result1);
}
}
// 1.编写一个类实现Callable接口
class MyCallable1 implements Callable {
// 2.重写call方法
@Override
public Object call() throws Exception {
// 3.将线程任务代码写在call方法中
int sum = 0;
for (int i = 0; i <= 100; i++) {
sum += i;
System.out.println(Thread.currentThread().getName() + "sum = " + sum);
}
return sum;
}
}
与线程休眠时间有关的方法
**static **void sleep(long time) | 让线程休眠指定的时间,单位为毫秒 |
---|
public class ThreadMethodDemo04 {
/*
休眠线程的方法
public static void sleep(long time):让线程休眠指定的时间,单位为毫秒
*/
public static void main(String[] args) throws InterruptedException {
for (int i = 5; i >= 0; i--) {
System.out.println("倒计时: " + i + " seconds");
Thread.sleep(1000);
}
}
}
与线程优先级有关的方法
setPriority(int newPriority) | 设置线程的优先级 |
---|---|
final int getPriority() | 获取线程的优先级 |
线程的调度方式
- 抢占式调度(随机)
- 非抢占式调度(轮流使用)
public class ThreadMethodDemo05 {
/*
线程优先级的方法:(只是能提高某一个线程抢到cpu的概率)
抢占式调度
public setPriority(int newPriority):设置线程优先级
public final int getPriority:获取线程优先级
优先级 1~10 (默认5)
*/
public static void